There are 2 View Controllers in my App.
The first "MainViewController" displays a tableView with CKRecords fields fetched from the private CloudKit database. Inside the viewWillAppear method of this VC I fetch records from CloudKit and reload data of a tableview to show the latest fetched results that have been previously saved in the CloudKit by the user.
The second view controller "CreateRecordViewController" is made for creating CKRecords and saving them to the private database of the CloudKit.
So i create records in the CreateRecordViewController and show them in the MainViewController.
The problem is the following: when I create record at CreateRecordViewController, it is saving on the CloudKit server, but after closing this CreateRecordViewController and going to MainViewController the tableview does not always update in time.
This is the code of saving record in my CreateRecordViewController:
CloudKitManager.sharedInstance.privateDatabase.save(myRecord) { (savedRecord, error) -> Void in
if error == nil {
print("successfully saved record code: \(savedRecord)")
}
else {
// Insert error handling
print("error Saving Data to iCloud: \(error.debugDescription)")
}
}
After record saved i close CreateRecordViewController and see MainViewController.
As i've said earlier in viewWillAppear of MainViewController i check if iCloud available, and if it is available, I fetch all records with a query from CloudKit and showing them in a tableView.
override func viewWillAppear(_ animated: Bool) {
CKContainer.default().accountStatus { (accountStatus, error) in
switch accountStatus {
case .noAccount: print("CloudKitManager: no iCloud Alert")
case .available:
print("CloudKitManager: checkAccountStatus : iCloud Available")
self.loadRecordsFromiCloud()
case .restricted:
print("CloudKitManager: checkAccountStatus : iCloud restricted")
case .couldNotDetermine:
print("CloudKitManager: checkAccountStatus : Unable to determine iCloud status")
}
}
}
In loadRecordsFromiCloud() I'm also reloading tableview async when query successful to show the latest results.
My loadRecordsFromiCloud method located in my MainViewController looks like this:
func loadRecordsFromiCloud() {
// Get a private Database
let privateDatabase = CloudKitManager.sharedInstance.privateDatabase
let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: "MyRecords", predicate: predicate)
let operation = CKQueryOperation(query: query)
privateDatabase.perform(query, inZoneWith: nil) { (results, error) in
if ((error) != nil) {
// Error handling for failed fetch from public database
print("error loading : \(error)")
}
else {
// Display the fetched records
//print(results!)
self.tableViewDataArray = results!
DispatchQueue.main.async {
print("DispatchQueue.main.sync")
self.tableView.reloadData()
}
}
}
}
Sometimes when CloudKit servers work faster i can see the new records in a tableView, but most of the time there is a delay (i don't see the new results in a tableview at the moment when MainViewController loads) I think this is because when i fetch records it fetches the old data (not sure why), but maybe i've made another mistake . This is a bad user experience and i would like to know how to avoid this delay. I want my tableView to show the updated results just after i close CreateRecordViewController .
My first idea was to subscribe to CloudKit Records changes, and fetch and reload data in a tableView when notification received, but i really don't need a push notification (i'd rather have just a method in code where i could fetch data from CloudKit after i know that all CloudKit records saved or after i know that there is a new record created, and after fetching and getting the data for a tableView i would call tableView.reloadData for example), but i'm not sure how to implement this right (in what method) and not sure if this is the best solution. I've also heard that in WWDC 2016 video dedicated to CloudKit, that now there are some new methods related to subscription to Record changes, maybe some of those methods can help (not sure). Looking for the best, or any good and easy solution for this problem (Delay Problem).
I'm using XCode 8, iOS 10, swift 3