CloudKit - 具有依赖性的CKQueryOperation

Cha*_*lie 6 ios swift cloudkit

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

背景信息

在WWDC 2015上,苹果发表了关于CloudKit的演讲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)
Run Code Online (Sandbox Code Playgroud)

示例结构

测试项目数据库包含宠物及其所有者,它看起来像这样:

|Pets               |   |Owners     |
|-name              |   |-firstName |
|-birthdate         |   |-lastName  |
|-owner (Reference) |   |           |
Run Code Online (Sandbox Code Playgroud)

我的问题

我试图找到属于所有者的所有宠物,我担心我正在创建链苹果警告.请参阅下面的两种方法,它们可以做同样的事情,但有两种方法.哪个更正确或者都错了?我觉得我在做同样的事情,但只是使用完成块.

我很困惑如何更改otherSearchBtnClick:使用依赖项.我需要在哪里添加

ownerQueryOp.addDependency(queryOp)
Run Code Online (Sandbox Code Playgroud)

在otherSearchBtnClick:?

@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)
}
Run Code Online (Sandbox Code Playgroud)

Edw*_*eer 1

理论上,您可以有多个所有者,因此可以有多个依赖项。此外,内部查询将在外部查询执行后创建。您将来不及创建依赖项。在您的情况下,强制内部查询的执行可能更容易到一个单独的队列,如下所示:

if record != nil {
    for owner in record {
        NSOperationQueue.mainQueue().addOperationWithBlock {
Run Code Online (Sandbox Code Playgroud)

这样,您将确保每个内部查询都将在新队列上执行,同时父查询可以完成。

其他:为了使代码更简洁,如果 for 循环内的所有代码都在一个单独的函数中,并以 CKReference 作为参数,那就更好了。