Добавление блока завершения в функцию CloudKit

Мой ViewController хочет отображать некоторые данные на основе запроса CloudKit.

Мой код CloudKit находится в отдельном классе. В этом классе есть функция loadExpenses(), которая извлекает некоторые сущности расходов из CK.

Я хочу иметь возможность вызывать loadExpenses() из VC, поэтому мне нужен блок завершения, предоставляемый функцией для обновления пользовательского интерфейса из VC.

Вот как выглядит 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 и получать/использовать блок завершения для обновления этих свойств. Как я могу это сделать?


person Diego Petrucci    schedule 14.02.2016    source источник


Ответы (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)
        }
    }
}
person konrad.bajtyngier    schedule 14.02.2016
comment
Спасибо. Не могли бы вы отредактировать свой ответ, предоставив пример кода? - person Diego Petrucci; 14.02.2016
comment
Я попытался собрать для вас код, см. отредактированный ответ. - person konrad.bajtyngier; 14.02.2016