I have added iCloud support to my app. when the user update his data I got a notification NSPersistentStoreDidImportUbiquitousContentChangesNotification
That's great
However, I have these problems
will
version of this notification that I can use to show loader for example that the database will be updatedwill
version, then I used the same notification to display a loader to tell the user that the database is being updated ... The problem in this notification is that it can be called several time if the content changed in iCloud is relatively large which lead me to display several loading indicator !.
I added iCloud support to Core data by doing this:
in NSManagedObjectContext
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
in NSPersistentStoreCoordinator
[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:@{NSPersistentStoreUbiquitousContentNameKey:@"iCloudStore"} error:nil];
and In NSPersistentStoreDidImportUbiquitousContentChangesNotification
notification method
- (void)persistentStoreDidImportUbiquitousContentChanges:(NSNotification *)notification
{
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
[managedObjectContext performBlock:^{
[managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
dispatch_async(dispatch_get_main_queue(), ^{
UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
MBProgressHUD *hud = [MBProgressHUD HUDForView:mainWindow];
if (hud == nil) {
hud = [[MBProgressHUD alloc] initWithWindow:mainWindow];
}
[mainWindow addSubview:hud];
hud.labelText = NSLocalizedString(@"Progress updated", nil);
[hud show:YES];
[hud hide:YES afterDelay:1];
// Post Notification
[[NSNotificationCenter defaultCenter] postNotificationName:RESET_APPLICATION_NOTIFICATION object:nil];
});
}];
}
The next time you need to store data, you should have a better idea of your options. Core Data is unnecessary for random pieces of unrelated data, but it's a perfect fit for a large, relational data set. The defaults system is ideal for small, random pieces of unrelated data, such as settings or the user's preferences.
Core Data is an object graph and persistence framework provided by Apple in the macOS and iOS operating systems. It was introduced in Mac OS X 10.4 Tiger and iOS with iPhone SDK 3.0. It allows data organized by the relational entity–attribute model to be serialized into XML, binary, or SQLite stores.
Yes. It's a pretty old framework and its Objective-C roots are not very well hidden. Regardless, Apple's clearly still interested in having people use and adopt Core Data given the fact that they've added new features for Core Data + SwiftUI in iOS 15, and previous iOS versions received various Core Data updates too.
Sync user data between multiple apps from the same developer If you have a suite of apps, they can all share the same CloudKit container so users can have access to their data for all of your apps on every device they have associated with their iCloud account.
I can't find a will version of this notification that I can use to show loader for example that the database will be updated
Yeah, that's because there isn't one. When new changes come in, the iCloud daemon saves them and then tells you what it has done.
Since I can't find a will version, then I used the same notification to display a loader to tell the user that the database is being updated ... The problem in this notification is that it can be called several time if the content changed in iCloud is relatively large which lead me to display several loading indicator !
Yes! I had this same issue. These notifications can be very frequent, so you don't want to notify the user every time one comes in. What I did was arrange to delay the notification until iCloud had quieted down for at least 1 second. You can do this using an NSTimer
. First declare it as a property:
@property (readwrite, retain) NSTimer *iCloudUpdateTimer;
Then when you get the "did import" notification, do something like this:
if (self.iCloudUpdateTimer == nil) {
self.iCloudUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(notifyUser:)
userInfo:nil
repeats:NO];
} else {
[self.iCloudUpdateTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:1.0];
}
// Now actually handle the notification....
What this does: Creates the timer if it doesn't exist. If it does exist, it delays the fire date for one second. When iCloud sends a lot of notifications, the timer keeps getting pushed out into the future. The timer will finally fire one second after iCloud calms down.
Then when the timer fires, do something like:
- (void)notifyUser:(NSNotification *)notification
{
[self.iCloudUpdateTimer invalidate];
self.iCloudUpdateTimer = nil;
// Then notify the user
}
You may need to use dispatch_async
to make sure that all timer access happens on the same queue.
(As an aside, even if there were a "will import" notification, it would probably be posted just as often as the current "did import" notification, so it wouldn't help you very much.)
Is there a way that I can use to trigger the update through iCloud manually?
No, you have absolutely no control over that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With