簡體   English   中英

正確使用后台獲取完成處理程序

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM