1

私の ViewController は、CloudKit クエリに基づいていくつかのデータを表示したいと考えています。

私の CloudKit コードはすべて別のクラスにあります。そのクラスには、CK から一部の Expenses エンティティをフェッチする loadExpenses() という関数があります。

VC から loadExpenses() を呼び出せるようにしたいので、VC から UI を更新する関数によって提供される完了ブロックが必要です。

loadExpenses() は次のようになります。

func loadExpenses() {
    let pred = NSPredicate(value: true)
    let sort = NSSortDescriptor(key: "creationDate", ascending: true)
    let query = CKQuery(recordType: "Expense", predicate: pred)
    query.sortDescriptors = [sort]

    let operation = CKQueryOperation(query: query)
    operation.desiredKeys = ["person", "action", "amount", "timestamp"]
    operation.resultsLimit = 50

    var newExpenses = [Expense]()

    operation.recordFetchedBlock = { (record) in
        let recordID = record.recordID
        let person = record["person"] as! String
        let action = record["action"] as! String
        let amount = record["amount"] as! Double
        let timestamp = record["timestamp"] as! NSDate
        let expense = Expense(person: person, action: action, amount: amount, timestamp: timestamp)
        newExpenses.append(expense)
    }

    // This is the part that needs to be changed
    operation.queryCompletionBlock = { [unowned self] (cursor, error) in
        dispatch_async(dispatch_get_main_queue()) {
            if error == nil {
                self.objects = newExpenses
                self.tableView.reloadData()
                self.refreshRealmDataFromCK()
            } else {
                let ac = UIAlertController(title: "Fetch failed", message: "There was a problem fetching the list of expenses; please try again: \(error!.localizedDescription)", preferredStyle: .Alert)
                ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
                self.presentViewController(ac, animated: true, completion: nil)
            }
        }
    }
    CKContainer.defaultContainer().privateCloudDatabase.addOperation(operation)
}

これらすべての self.property が VC に属していることを考えると、明らかに最後の部分は実行されません (VC で何をする必要があるかを示すためだけにそれらを保持しました)。

私が言ったように、VC からこの関数を呼び出し、完了ブロックを取得/使用して、これらのプロパティを更新できるようにしたいと考えています。それ、どうやったら出来るの?

4

1 に答える 1

1

ブロックをパラメーターとして関数に渡す必要がありloadExpenses()ます。したがって、実際には のように定義する必要がありますloadExpenses(completionBlock:([whatever parameters you need in here])->Void)

次に、渡されたcompletionBlockブロックを (適切なパラメーターを使用して)operation.queryCompletionBlockブロック内から呼び出すことができます。

編集:

したがって、これはもちろんまったくテストされていませんが、試してみることができます。

func loadExpenses(completionBlock:([Expense])->Void) {
    let pred = NSPredicate(value: true)
    let sort = NSSortDescriptor(key: "creationDate", ascending: true)
    let query = CKQuery(recordType: "Expense", predicate: pred)
    query.sortDescriptors = [sort]

    let operation = CKQueryOperation(query: query)
    operation.desiredKeys = ["person", "action", "amount", "timestamp"]
    operation.resultsLimit = 50

    var newExpenses = [Expense]()

    operation.recordFetchedBlock = { (record) in
        let recordID = record.recordID
        let person = record["person"] as! String
        let action = record["action"] as! String
        let amount = record["amount"] as! Double
        let timestamp = record["timestamp"] as! NSDate
        let expense = Expense(person: person, action: action, amount: amount, timestamp: timestamp)
        newExpenses.append(expense)
    }

    // This is the part that needs to be changed
    operation.queryCompletionBlock = { [unowned self] (cursor, error) in
        completionBlock(newExpenses)
    }
    CKContainer.defaultContainer().privateCloudDatabase.addOperation(operation)
}

そして、次のように呼び出します。

loadExpenses({ (newExpenses:[Expense]) -> Void in {
    dispatch_async(dispatch_get_main_queue()) {
        if error == nil {
            self.objects = newExpenses
            self.tableView.reloadData()
            self.refreshRealmDataFromCK()
        } else {
            let ac = UIAlertController(title: "Fetch failed", message: "There was a problem fetching the list of expenses; please try again: \(error!.localizedDescription)", preferredStyle: .Alert)
            ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
            self.presentViewController(ac, animated: true, completion: nil)
        }
    }
}
于 2016-02-14T16:56:08.830 に答える