CloudKit - 具有依赖项的 CKQueryOperation

2024-02-22

我刚刚开始使用 CloudKit,所以请耐心等待。

背景信息

苹果在 WWDC 2015 上发表了有关 CloudKit 的演讲https://developer.apple.com/videos/wwdc/2015/?id=715 https://developer.apple.com/videos/wwdc/2015/?id=715

在本次演讲中,他们警告不要创建链接查询,而是推荐这种策略:

let firstFetch = CKFetchRecordsOperation(...)
let secondFetch = CKFetchRecordsOperation(...)
...
secondFetch.addDependency(firstFetch)

letQueue = NSOperationQueue()
queue.addOperations([firstFetch, secondFetch], waitUntilFinished: false)

结构示例

测试项目数据库包含宠物及其主人,如下所示:

|Pets               |   |Owners     |
|-name              |   |-firstName |
|-birthdate         |   |-lastName  |
|-owner (Reference) |   |           |

我的问题

我正在尝试找到属于某个主人的所有宠物,并且我担心我正在创建苹果警告的连锁店。请参阅下面的两种方法,它们执行相同的操作,但有两种方式。哪个更正确,或者两者都是错误的?我觉得我在做同样的事情,但只是使用完成块。

我对如何更改 otherSearchBtnClick: 以使用依赖项感到困惑。我需要在哪里添加

ownerQueryOp.addDependency(queryOp)

在其他SearchBtn中点击:?

@IBAction func searchBtnClick(sender: AnyObject) {
    var petString = ""
    let container = CKContainer.defaultContainer()
    let publicDatabase = container.publicCloudDatabase
    let privateDatabase = container.privateCloudDatabase

    let predicate = NSPredicate(format: "lastName == '\(ownerLastNameTxt.text)'")
    let ckQuery = CKQuery(recordType: "Owner", predicate: predicate)
    publicDatabase.performQuery(ckQuery, inZoneWithID: nil) {
        record, error in
        if error != nil {
            println(error.localizedDescription)
        } else {
            if record != nil {
                for owner in record {
                    let myRecord = owner as! CKRecord
                    let myReference = CKReference(record: myRecord, action: CKReferenceAction.None)

                    let myPredicate = NSPredicate(format: "owner == %@", myReference)
                    let petQuery = CKQuery(recordType: "Pet", predicate: myPredicate)
                    publicDatabase.performQuery(petQuery, inZoneWithID: nil) {
                        record, error in
                        if error != nil {
                            println(error.localizedDescription)
                        } else {
                            if record != nil {
                                for pet in record {
                                    println(pet.objectForKey("name") as! String)

                                }

                            }
                        }
                    }
                }
            }
        }
    }
}

@IBAction func otherSearchBtnClick (sender: AnyObject) {
    let container = CKContainer.defaultContainer()
    let publicDatabase = container.publicCloudDatabase
    let privateDatabase = container.privateCloudDatabase

    let queue = NSOperationQueue()
    let petPredicate = NSPredicate(format: "lastName == '\(ownerLastNameTxt.text)'")
    let petQuery = CKQuery(recordType: "Owner", predicate: petPredicate)
    let queryOp = CKQueryOperation(query: petQuery)
    queryOp.recordFetchedBlock = { (record: CKRecord!) in
        println("recordFetchedBlock: \(record)")
        self.matchingOwners.append(record)
    }

    queryOp.queryCompletionBlock = { (cursor: CKQueryCursor!, error: NSError!) in
        if error != nil {
            println(error.localizedDescription)
        } else {
            println("queryCompletionBlock: \(cursor)")
            println("ALL RECORDS ARE: \(self.matchingOwners)")
            for owner in self.matchingOwners {
                let ownerReference = CKReference(record: owner, action: CKReferenceAction.None)
                let ownerPredicate = NSPredicate(format: "owner == %@", ownerReference)
                let ownerQuery = CKQuery(recordType: "Pet", predicate: ownerPredicate)
                let ownerQueryOp =  CKQueryOperation(query: ownerQuery)
                ownerQueryOp.recordFetchedBlock = { (record: CKRecord!) in
                    println("recordFetchedBlock (pet values): \(record)")
                    self.matchingPets.append(record)
                }
                ownerQueryOp.queryCompletionBlock = { (cursor: CKQueryCursor!, error: NSError!) in
                    if error != nil {
                        println(error.localizedDescription)
                    } else {
                        println("queryCompletionBlock (pet values)")
                        for pet in self.matchingPets {
                            println(pet.objectForKey("name") as! String)
                        }
                    }
                }
            publicDatabase.addOperation(ownerQueryOp)
            }
        }


    }
    publicDatabase.addOperation(queryOp)
}

如果您不需要取消并且不担心在网络错误上重试,那么我认为您可以很好地链接查询。

我知道我知道,在 WWDC 2015 中,Nihar Sharma 推荐了添加依赖项方法,但看起来他只是在最后没有考虑太多就将其添加了。您会看到不可能重试 NSOperation,因为它们无论如何都是一次性的,并且他没有提供取消队列中已有操作的示例,也没有提供如何从一个操作传递数据到下一个操作的示例。鉴于这 3 个复杂问题可能需要数周时间才能解决,请坚持现有工作,等待下届 WWDC 的解决方案。另外,块的全部意义在于让您调用内联方法并能够访问上述方法中的参数,因此如果您转向操作,您就无法充分利用该优势。

他不使用链接的主要原因是荒谬的,他无法分辨哪个错误是针对哪个请求的,他将他的错误命名为 someError 然后 otherError 等。没有一个头脑正常的人会在块内命名不同的错误参数,所以只需使用所有这些都具有相同的名称,然后您就知道在一个块内您始终使用正确的错误。因此,他是创建混乱场景并为其提供解决方案的人,但是最好的解决方案是首先不要创建多个错误参数名称的混乱场景!

话虽如此,如果您仍然想尝试使用操作依赖项,这里有一个示例说明如何完成此操作:

__block CKRecord* venueRecord;
CKRecordID* venueRecordID = [[CKRecordID alloc] initWithRecordName:@"4c31ee5416adc9282343c19c"];
CKFetchRecordsOperation* fetchVenue = [[CKFetchRecordsOperation alloc] initWithRecordIDs:@[venueRecordID]];
fetchVenue.database = [CKContainer defaultContainer].publicCloudDatabase;

// init a fetch for the category, it's just a placeholder just now to go in the operation queue and will be configured once we have the venue.
CKFetchRecordsOperation* fetchCategory = [[CKFetchRecordsOperation alloc] init];

[fetchVenue setFetchRecordsCompletionBlock:^(NSDictionary<CKRecordID *,CKRecord *> * _Nullable recordsByRecordID, NSError * _Nullable error) {
    venueRecord = recordsByRecordID.allValues.firstObject;
    CKReference* ref = [venueRecord valueForKey:@"category"];

    // configure the category fetch
    fetchCategory.recordIDs = @[ref.recordID];
    fetchCategory.database = [CKContainer defaultContainer].publicCloudDatabase;
}];

[fetchCategory setFetchRecordsCompletionBlock:^(NSDictionary<CKRecordID *,CKRecord *> * _Nullable recordsByRecordID, NSError * _Nullable error) {
    CKRecord* categoryRecord = recordsByRecordID.allValues.firstObject;

    // here we have a venue and a category so we could call a completion handler with both.
}];

NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[fetchCategory addDependency:fetchVenue];
[queue addOperations:@[fetchVenue, fetchCategory] waitUntilFinished:NO];

它的工作原理是首先获取 Venue 记录,然后获取其类别。

抱歉,没有错误处理,但正如您所看到的,已经有大量代码可以通过链接在几行中完成某些操作。就我个人而言,我发现这个结果比简单地将便捷方法链接在一起更复杂和令人困惑。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CloudKit - 具有依赖项的 CKQueryOperation 的相关文章

  • 设置/覆盖 UICollectionView 中单元格之间的填充

    我有一个 UICollectionView 但在获取单元格之间的填充时遇到了问题 理论上 我应该能够将屏幕除以 4 并且我可以获得包含 4 个图像的单元格大小 完美地占据屏幕宽度 但是 它选择不这样做 相反 它会创建 3 个具有巨大填充的图
  • AVCaptureSession 具有多个方向问题

    我正在尝试实现条形码扫描仪 我有一个 AVCaptureSession 它从 AVCaptureDevice 接收视频 我想支持所有方向 使用以下代码 当我运行应用程序时 纵向一切正常 然而 在横向方向上 视图会旋转 但视频输入不会旋转 所
  • 如何使用完成处理程序等待 firestore 请求的完成

    我正在慢慢地了解完成处理程序 如果我有一个 firestore 查询 如果我想使用完成处理程序 则有点向后工作 当 firestore 查询完成时 我必须使用completion 但它的设置功能仍然让我感到困惑 因此 如果这是一个将闭包作为
  • SwiftUI:状态栏颜色

    有没有办法将 SwiftUI 视图的状态栏更改为白色 我可能错过了一些简单的东西 但我似乎找不到在 SwiftUI 中将状态栏更改为白色的方法 到目前为止我只看到 statusBar hidden Bool 状态栏文本 色调 前景色可以通过
  • UIDocumentInteractionController 阻止“打开方式”表中的空投

    在我的应用程序中 我允许用户通过 Instagram 分享照片 这需要使用 UIDocumentInteractionController 如果手机支持 则会自动检测空投 如何将其从 打开方式 操作表中删除 即使我使用 UIActivity
  • 在iOS上,“添加到主页”缓存保存在哪里,如何清除它?

    我正在 iPad iOS v7 上制作一个 html5 游戏 当我将其添加到主页时 它非常顽固地释放缓存 如果我在 Safari 中查看它 这会按照您所期望的方式工作 如果我刷新一次或两次 页面就会以最新状态缓存 但在主页上却是另一回事 它
  • 所需框架与静态库

    构建现代框架 https developer apple com videos play wwdc2014 416 says 每个应用程序都有自己的自定义框架副本 https stackoverflow com a 15262463 242
  • 添加自定义过渡会导致 xib 加载错误的屏幕尺寸

    我正在尝试向具有 xib 的 UIViewController 添加自定义过渡 我尝试了几种方法 但它们都有相同的问题 视图显示的屏幕尺寸错误 我当前的示例基于以下教程 使用 Swift 在 iOS 中自定义 UIViewControlle
  • 在真实设备上展示测试广告

    这是我的代码 let request GADRequest request testDevices kGADSimulatorID XXXX2F32d69CCA859FFB559D0FEA3CF6483D08A6 adView load r
  • iOS:提高图像绘制速度

    我有一系列想要制作动画的图像 UIImageView支持一些基本的动画 但不足以满足我的需求 我的第一个方法是使用UIImageView并设置image当图像属性 这太慢了 速度慢的原因是图像的绘制 这让我感到惊讶 我以为瓶颈会加载图像 我
  • Xcode 中的 iOS 9 警告 - 此文件设置为针对早于项目部署的版本进行构建。功能可能有限

    我刚刚将我的 Mac 更新到最新的操作系统 并将 Xcode 更新到最新版本 现在我收到此警告 但我不知道该由谁来删除它 也不知道它的真正含义是什么 有人可以向我解释一下吗 Thanks Select Main storyboard in
  • 检测 AvPlayer 何时切换比特率

    在我的应用程序中 我使用 AVPlayer 通过 HLS 协议读取一些流 m3u8 文件 我需要知道在流会话期间 客户端切换比特率多少次 我们假设客户端的带宽正在增加 因此客户端将切换到更高比特率的段 AVPlayer能检测到这个开关吗 T
  • 我怎样才能勾勒出文本字体?

    我想在边框 轮廓 中显示另一种颜色的文本 我正在尝试使用在 MapOverlayView 中显示文本 text drawAtPoint CGPointMake 0 30 withFont UIFont fontWithName Helvet
  • 在 Swift 中使用 CommonCrypto 解密时出现问题

    我在一家Swift only加密 解密Extension for String and NSData 并且 crypt 部分的工作基于 Zaph 在链接问题中提供的答案 在 Swift 中使用 CCCrypt CommonCrypt 时出现
  • SKNode 上的 runAction 未完成

    我使用 NSOperation 子类来获取串行执行SKAction正如这个问题中所描述的 如何在 Swift 中子类化 NSOperation 以将 SKAction 对象排队以进行串行执行 https stackoverflow com
  • 苹果企业程序分发问题[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 这个问题涉及到Apple iOS 开发者企业计划 http developer apple com programs ios enterprise 我
  • 避免 UIImage 的 imageNamed - 内存管理

    我正在经历这个链接 http akosma com 2009 01 28 10 iphone memory management tips 我遇到了一个点避免 UIImage 的 imageNamed 出于什么原因我们应该避免这种情况 它会
  • 分发内部业务 IOS 应用程序

    我遇到了 IOS 应用程序分发的一个令人困惑的部分 因此 我需要简单细分一下我的限制 即仅将我的应用程序分发给我的员工 同事或任何被视为 内部 的人 这是表明我不希望该应用程序出现在应用程序商店中的另一种方式 我的情况是我为几家公司开发 他
  • RemoteIO 音频单元播放回调中的 AudioBufferList 内容

    我想 拦截 音频数据传送到 iOS 设备扬声器的过程 我相信这可以使用 RemoteIO 音频单元和回调来完成 在下面的playbackCallback中 ioData实际上包含任何音频数据吗 static OSStatus playbac
  • IPV6 快速可达性

    我是 swift 和 xcode 的新手 并且我的应用程序因 IPV6 而被拒绝 性能 2 1 当我们执行以下操作时 您的应用程序会在运行 iOS 9 3 5 并连接到 IPv6 网络的 iPad 和 iPhone 上崩溃 具体来说 当我们

随机推荐

  • Python google app engine 的最佳部署策略

    我想知道是否有在 Google 应用程序引擎 特别是 Django 上部署 python 应用程序的最佳实践 模式 最佳实践应该是现有最佳实践的组合 即 Fabric Paver Buildout 等 另请分享开发的最佳实践模式 我无法让
  • 我可以在yield-return-method 中使用“using”吗?

    我刚刚看到了一个 YouTube 视频 其中导师使用了一个 Yield 返回方法来打开一个文件并从中读取行 这些行将 Yield 返回给调用者 实际代码位于 FileStream 周围的 using 块中 然后我想知道 在yield ret
  • 超时后消除反应错误消息

    我试图显示一些反应错误消息并在 5 秒超时后隐藏它们 下面是代码 import as React from react import ErrorInfo from Twilio api export const Error type mes
  • 在 C++ 中设置默认浮点打印精度

    我想在比较过程中控制双精度数的精度 然后使用 C 恢复到默认精度 我打算使用setPrecision 设置精度 那么将精度设置回默认值的语法 如果有 是什么 我正在做这样的事情 std setPrecision math log10 m F
  • 向 xml 文档添加注释

    Code from lxml import etree Create the network XML file tree root etree Element network tree etree ElementTree root Crea
  • 编译元素导致输入插入符位置移动到末尾

    我的指令有问题 该指令的目的是轻松添加验证 而无需手动将 ng class 除其他外 添加到元素中以便显示错误状态 我只是想在我的元素上放置一个 验证 指令 并在出现错误状态时生成适当的类 和错误消息 就验证而言 它运行良好 但会产生奇怪的
  • 自定义路由类

    在 symfony 1 4 中 您可以定义自定义路由类 在其中使用自定义逻辑覆盖 url 的生成 例如 custom class sfDoctrineRouteCollection options model Custom prefix p
  • 如何在jquery中选择一个元素及其子元素? [复制]

    这个问题在这里已经有答案了 我有一个 div 其中包含更多 div 这些 div 内部包含 table div 我怎样才能在jquery中选择这个父div及其子div 父 div 有类 AccordionTitle AccordionTit
  • 当我尝试使用 Rakudo 运行脚本时,为什么会出现“被零除”错误?

    我刚刚构建了 Rakudo 和 Parrot 这样我就可以使用它并开始学习 Perl 6 我下载了 Perl 6 书 并愉快地输入了第一个演示程序 网球锦标赛示例 当我尝试运行该程序时 出现错误 Divide by zero current
  • 即使活动发生变化,如何保持 Android 客户端与服务器的连接并向服务器发送数据?

    我最初在我的活动中实现了一个异步任务 将数据发送到服务器 但是当我改变活动时 连接就丢失了 为了避免这种情况 我的方法是实现一个集中网络操作并将数据发送到服务器的服务 该服务的代码如下 import java io BufferedWrit
  • Rxjs 将 Json 文档中的数组映射到新的数组类型

    我正在 Angular 服务中从 PouchDB 检索文档 该文档以以下格式检索 id segments rev 1 4f0ed65cde23fe724db13bea1ae3bb13 segments name Aerospace name
  • 并发 Sql Server 连接数

    我正在创建一个带有 Sql Server 数据库引擎的 net 应用程序 我希望每秒有数千名用户访问我的网站 连接数靠什么 IIS 和 Sql Server 可以容纳多少个连接 首先 连接和连接池之间存在区别 研究一下这一点是不是很好 因为
  • RabbitMQ 用户在预先创建的队列上发布/订阅的权限

    我有一个用例 我需要创建一个用户并授予他仅在现有队列上发布 订阅的权限 这是一个示例 虚拟主机 mainvhost 对于所有用户都相同 在虚拟主机内 我有 A foo 和 Q bar 队列 用户 foo 只能发布 订阅到 Q foo 用户
  • 如何断言不为空?

    我对 javascript 测试非常陌生 我想知道如何在中断言 not nullMocha框架 Mocha 支持您想要的任何断言库 您可以在此处查看它如何处理断言 http mochajs org assertions http mocha
  • Primefaces 仅更新选定的选项卡

    我有一种情况 当触发 选择 事件时 我想更新页面上的多个组件 However 其中两个位置位于 tabView 内 我只想更新这些组件 如果它们位于当前选定的选项卡内 我suspect我正在寻找的是这样的东西
  • 与“开始调试”相比,“附加到进程”有什么优势?

    我是编程新手 我知道之前只开始调试 也许启动调试套件以更好地开发一些小型应用程序 我发现 Visual Studio IDE 提供了另一种附加到进程的方法供使用 何时以及为何必须使用附加调试 比如多线程应用程序的调试 客户端 服务应用程序调
  • 如何读取大型 Sqlite 文件并从资产文件夹复制到 Android 模拟器或设备中?

    我想很多人已经读过这篇文章 在 Android 应用程序中使用您自己的 SQLite 数据库 http www reigndesign com blog using your own sqlite database in android a
  • ASP.Net 动态数据还是 MVC2?

    我一直在使用 Web 表单 并且我想根据一些事实和我在其中看到的其他优点切换到 MVC 模式 当我遇到最新的动态数据 过去称为动态数据模板 时 我对 MVC 审查进展顺利 如果我错了 请纠正我 但我相信在后端 MVC2 和 DD 都使用 M
  • 在其他桌面、Python、Windows 上启动进程

    我创建了第二个桌面 import win32api win32con win32gui win32service win32process import pywintypes import traceback thread time cSt
  • CloudKit - 具有依赖项的 CKQueryOperation

    我刚刚开始使用 CloudKit 所以请耐心等待 背景信息 苹果在 WWDC 2015 上发表了有关 CloudKit 的演讲https developer apple com videos wwdc 2015 id 715 https d