![](/img/trans.png)
[英]Call completion handler on background fetch with multiple NSURLSessions
[英]Correct use of background fetch completion handler
我的應用程序使用CloudKit,我正在嘗試實現后台獲取。
App Delegate中的方法在我的主視圖控制器中調用一個方法,該方法檢查CloudKit數據庫中的更改。
但是,我意識到我沒有正確調用完成處理程序,因為CloudKit的閉包將異步返回。 我真的不確定一旦操作完成,如何最好地在應用程序委托方法中調用完成處理程序。 我可以將完成處理程序傳遞給視圖控制器方法嗎?
應用程序委托
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
DispatchQueue.global(qos: .userInitiated).async {
// Code to get a reference to main view controller
destinationViewController.getZoneChanges()
completionHandler(.newData)
}
}
用於獲取CloudKit更改的主視圖控制器方法
// Fetch zone changes (a method in main table view controller)
func getZoneChanges() {
DispatchQueue.global(qos: .userInitiated).async {
let customZone = CKRecordZone(zoneName: "Drugs")
let zoneID = customZone.zoneID
let zoneIDs = [zoneID]
let changeToken = UserDefaults.standard.serverChangeToken // Custom way of accessing User Defaults using an extension
// Look up the previous change token for each zone
var optionsByRecordZoneID = [CKRecordZone.ID: CKFetchRecordZoneChangesOperation.ZoneOptions]()
// Some other functioning code to process options
// CK Zone Changes Operation
let operation = CKFetchRecordZoneChangesOperation(recordZoneIDs: zoneIDs, optionsByRecordZoneID: optionsByRecordZoneID)
// Closures for records changed, deleted etc.
// Closure details omitted for brevity as fully functional as expected.
// These closures change data model, Spotlight indexing, notifications and trigger UI refresh etc.
operation.recordChangedBlock = { (record) in
// Code...
}
operation.recordWithIDWasDeletedBlock = { (recordId, string) in
// Code...
}
operation.recordZoneChangeTokensUpdatedBlock = { (zoneId, token, data) in
UserDefaults.standard.serverChangeToken = changeToken
UserDefaults.standard.synchronize()
}
operation.recordZoneFetchCompletionBlock = { (zoneId, changeToken, _, _, error) in
if let error = error {
print("Error fetching zone changes: \(error.localizedDescription)")
}
UserDefaults.standard.serverChangeToken = changeToken
UserDefaults.standard.synchronize()
}
operation.fetchRecordZoneChangesCompletionBlock = { (error) in
if let error = error {
print("Error fetching zone changes: \(error.localizedDescription)")
} else {
print("Changes fetched successfully!")
// Save local items
self.saveData() // Uses NSCoding
}
}
CKContainer.default().privateCloudDatabase.add(operation)
}
}
更新您的getZoneChanges
以具有完成參數。
func getZoneChanges(completion: @escaping (Bool) -> Void) {
// the rest of your code
operation.fetchRecordZoneChangesCompletionBlock = { (error) in
if let error = error {
print("Error fetching zone changes: \(error.localizedDescription)")
completion(false)
} else {
print("Changes fetched successfully!")
completion(true)
}
}
}
然后,您可以更新應用程序委托方法以使用它:
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
DispatchQueue.global(qos: .userInitiated).async {
// Code to get a reference to main view controller
destinationViewController.getZoneChanges { (success) in
completionHandler(success ? .newData : .noData)
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.