NSManagedObjectContext *moc = [self managedObjectContext];
[moc performBlock:^{
[moc mergeChangesFromContextDidSaveNotification:notification];
}];
}
6.4 Under the Hood
Now that we have looked at how to integrate iCloud into our Core Data–based application, it is helpful to understand exactly how it works under the hood.
Debug Output
Core Data has several logging levels that we can turn on to watch all of the SQL calls that are generated during an application’s life cycle. There are currently three levels to this debugging log, with level 1 being the least chatty and level 3 being the most chatty. We can set this debug output by adding the runtime parameter com.apple.CoreData.SQLDebug to our application and pass along with it the level we want to be set.
In addition to the Core Data debug setting, we can also turn on an additional setting to watch all of the chatter between Core Data and iCloud. That addi-tional setting is com.apple.coredata.ubiquity.logLevel. For an unknown reason, this logging code responds only to level 3, as shown in Figure 18, Turning on iCloud debugging, on page 111.
Looking at these logs, we can see there is a tremendous amount of activity going on behind the scenes. We can also examine the frequency with which Core Data starts a sync with iCloud and use that information when we are determining how often to generate saves from our application.
Chapter 6. Using iCloud
•
110Figure 18—Turning on iCloud debugging
The logs can also help us watch for corruption, which appears to occur most frequently during development. Without logging’s early warning system, cor-ruption can be quite frustrating when it happens. Without the aid of logging, things just stop. No errors are generated; iCloud just stops working. With logging turned on, we can glean when something goes wrong.
Unfortunately, at this time, there is no way to determine at runtime, within our application, that corruption has occurred.
Further, once a log file has been corrupted, there is no way to clear it out.
The best that we can do is to start over with a new file.
This is currently being tracked under rdar://10837238. Transaction Logs
iCloud functions through transaction logs. Similar to how modern version control systems work, every time a save is performed by an “iCloud-backed”
persistent store, a transaction log is created that details what happened in that save. These transaction logs are kept in order and pushed up to the cloud. On other devices, the transaction logs are received and played back
onto the receiving persistent store. Through this process, each persistent store is kept in sync with the other. In addition, new persistent stores can be added to the mix by simply starting with an empty store and playing back the transactions one at a time until the new store is brought up-to-date.
If the application has seen a lot of activity, there can be a large number of transaction logs. The large number of transaction logs means any new device must take a significant amount of time to “catch up” with the current state of the persistent store. For this reason, Core Data cuts a new “baseline” on a regular interval. A baseline is effectively a “roll-up” of the transaction logs to a certain point. Any logs after the baseline point will pile up as before. A new store coming into the sync starts with a baseline instead of an empty database and consumes any transaction logs generated after the baseline.
This strategy keeps the amount of time it takes to bring a new persistent store up to speed to a minimum.
Turning Off iCloud
Currently, there is an outstanding issue when the user turns off iCloud. When this event occurs, our application receives no notification. The data simply goes away. Some developers have been successful in adding a “sentinel” file to the ubiquitous container (via the URL that gets resolved when we configure iCloud) and monitoring that file. If the file goes away, then we can decide how to handle the state change. Creating a sentinel file has not been approved (or disallowed) by Apple, and this solution may not work in future versions of Core Data.
Ordered Relationships Are Not Allowed
If we integrate iCloud into our application, we cannot use the new ordered relationships that were added as of iOS 6.0 and OS X 10.8. iCloud integration does not work with ordered relationships. Ideally, this deficiency will be cor-rected at some point.
Data Migration
An additional limiting factor with iCloud integration is the use of lightweight migration. Heavy-weight migration (as in a migration that requires a mapping model) cannot be used if iCloud is enabled. With an iCloud-enabled NSPersis-tentStore, the mapping model will simply be ignored, and the migration fails.
Therefore, particular care must be taken when you are doing a migration to not cross the limit of lightweight/inferred migration. If a migration requires more complexity than a lightweight migration can handle, then it is recom-mended that a new ubiquitous container be set up, the migration be done Chapter 6. Using iCloud
•
112with iCloud turned off, and then the data be loaded into the new container.
To accomplish this, you would need to follow a procedure similar to the one detailed in Section 6.5, Migrating an Existing Application, on page 113.