«Introduction to Core Data Programming Guide 11 Who Should Read This Document 11 Organization of This Document 11 See Also 13 Technology Overview 14 ...»
to analyze the behavior of your application. There are several Instruments probes specific to Core Data:
Core Data Fetches ● Records invocations of executeFetchRequest:error:, providing information about the entity against which the request was made, the number of objects returned, and the time taken for the fetch.
Core Data Saves ● Records invocations of save: and the time taken to do the save.
Core Data Faults ● Records information about object and relationship fault firing. For object faults, records the object being faulted; for relationship faults, records the source object and the relationship being fired. In both cases, records the time taken to fire the fault.
Core Data Cache Misses ● Traces fault behavior that specifically results in filesystem activity—indicating that a fault was fired for which no data was available—and records the time taken to retrieve the data.
All the instruments provide a stack trace for each event so that you can see what caused it to happen.
When analyzing your application, you should of course also take into account factors not directly related to Core Data, such as overall memory footprint, object allocations, use and abuse of other API such as the key-value technologies and so on.
This article outlines some of the common issues encountered in applications that use Core Data and provides clues as to correcting the problem.
When troubleshooting Core Data-based applications, it is important to consider that Core Data provides functionality that builds on top of functionality provided by other parts of Cocoa. When attempting to diagnose a problem with an application that uses Core Data, you should take care to distinguish between issues that are specific to Core Data and those that arise because of an error with another framework or to an implementation or architectural patten. Poor performance, for example, may not be due to Core Data per se, but instead are due to a failure to observe standard Cocoa techniques of memory management or resource conservation; or if a user interface does not update properly, this may be due to an error in how you have configured Cocoa bindings.
Object Life-Cycle Problems Merge errors Problem: You see the error message, "Could not merge changes".
Cause: Two different managed object contexts tried to change the same data. This is also known as an optimistic locking failure.
Remedy: Either set a merge policy on the context, or manually (programmatically) resolve the failure. You can retrieve the currently committed values for an object using committedValuesForKeys:, and you can re-fault the object (so that when it is next accessed its data values are retrieved from its persistent store) using
Assigning a managed object to a different store Problem: You see an exception that looks similar to this example.
NSInvalidArgumentException [MyMO 0x3036b0_assignObject:toPersistentStore:]:
Can’t reassign an object to a different store once it has been saved.
2012-09-19 | Copyright © 2004, 2012 Apple Inc. All Rights Reserved.
Troubleshooting Core Data Object Life-Cycle Problems Cause: The object you are trying to assign to a store has already been assigned and saved to a different store.
Remedy: To move an object from one store to another, you must create a new instance, copy the information from the old object, save it to the appropriate store, and then delete the old instance.
Fault cannot be fulfilled Problem: You see the error message, "Core Data could not fulfill a fault".
Cause: The corresponding object's underlying data has been deleted from the persistent store.
Remedy: You should discard this object.
This problem can occur in at least two situations:
Start with a strong reference to a managed object.
● Delete the managed object via the managed object context.
● Save changes on the object context.
● At this point, the deleted object has been turned into a fault. It isn’t destroyed because doing so would violate the rules of memory management.
Try to retrieve an attribute or relationship from the previously retained reference.
● Core Data will try to fault the faulted managed object but will fail to do so because the object has been deleted from the store. That is, there is no longer an object with the same global ID in the store.
Delete an object from a managed object context.
● Fail to break all relationships from other objects to that object.
At this point, if you try to fire the relationship from some other object to that object, it may fail (this depends on the details of the configuration of the relationship as that affects how the relationship is stored).
The delete rules for relationships affect relationships only from the source object to other objects (including inverses). Without potentially fetching large numbers of objects, possibly without reason, there is no way for Core Data to efficiently clean up the relationships to the object.
2012-09-19 | Copyright © 2004, 2012 Apple Inc. All Rights Reserved.
Troubleshooting Core Data Object Life-Cycle Problems Keep in mind that a Core Data object graph is directional. That is, a relationship has a source and a destination.
Following a source to a destination does not necessarily mean that there is an inverse relationship. So, in that sense, you need to ensure that you are properly maintaining the object graph across deletes.
In practice, a well-designed object graph does not require much manual post-deletion clean up. If you consider that most object graphs have "entry points" that in effect act as a root node for navigating the graph and that most insertion and deletion events are rooted at those nodes just like fetches, then delete rules take care of most of the work for you. Similarly, since smart groups and other “casual” relationships are generally best implemented with fetched properties, various ancillary collections of entry points into the object graph generally do not need to be maintained across deletes because fetched relationships have no notion of permanence when it comes to objects found via the fetched relationship.
Managed object invalidated
Problem: You see an exception that looks similar to this example:
NSObjectInaccessibleException [MyMO 0x3036b0_assignObject:toPersistentStore:]:
The NSManagedObject with ID:#### has been invalidated.
Cause: Either you have removed the store for the fault you are attempting to fire, or the managed object's context has been sent a reset message.
Remedy: You should discard this object. If you add the store again, you can try to fetch the object again.
Class is not key-value coding compliant Problem: You see an exception that looks similar to the following example.
NSUnknownKeyException [MyMO 0x3036b0 valueForUndefinedKey:]:
this class is not key value coding-compliant for the key randomKey.
Cause: Either you used an incorrect key, or you initialized your managed object with init instead of
Remedy: Use a valid key (check the spelling and case carefully—also review the rules for key-value coding compliance in Key-Value Coding Programming Guide ), or ensure that you use the designated initializer for NSManagedObject (see initWithEntity:insertIntoManagedObjectContext:).
Entity class does not respond to invocations of custom methods Problem: You define an entity that uses a custom subclass of NSManagedObject, then in code you create an
instance of the entity and invoke a custom method, as illustrated in this code fragment:
NSManagedObject *entityInstance = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:managedObjectContext];
[entityInstance setAttribute: newValue];
You get a runtime error like this:
"2005-05-05 15:44:51.233 MyApp ***
-[NSManagedObject setNameOfEntity:]: selector not recognized [self = 0x30e340] Cause: In the model, you may have misspelled the name of the custom class for the entity.
Remedy: Ensure that the spelling of name of the custom class in the model matches the spelling of the custom class you implement.
Custom accessor methods are not invoked, key dependencies are not obeyed Problem: You define a custom subclass of NSManagedObject for a particular entity and implement custom accessors methods (and perhaps dependent keys). At runtime, the accessor methods are not called and the dependent key is not updated.
Cause: In the model, you did not specify the custom class for the entity.
Remedy: Ensure that the model specifies of name of the custom class for the entity (that is, that it is not NSManagedObject).
Problems with Fetching SQLite store does not work with sorting Problem: You create a sort descriptor that uses a comparison method defined by NSString, such as the
NSSortDescriptor *mySortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
You then either use this descriptor with a fetch request or as one of an array controller's sort descriptors. At
runtime, you might see an error message that looks similar to the following:
NSRunLoop ignoring exception 'unsupported NSSortDescriptor selector:
localizedCaseInsensitiveCompare:' that raised during posting of
delayed perform with target 3e2e42 and selector 'invokeWithTarget:'
Cause: Exactly how a fetch request is executed depends on the store—see “Fetching Managed Objects” (page 61).
Remedy: If you are executing the fetch directly, you should not use Cocoa-based sort operators—instead you should sort the returned array in memory. If you are using an array controller, you may need to subclass NSArrayController so you can have it not pass the sort descriptors to the database and instead do the sorting after your data has been fetched.
Problems with Saving SQLite store takes a "long time" to save Problem: You are using an SQLite store and notice that it takes longer to save to the SQLite store than it does to save the same data to an XML store.
Cause: This is probably expected behavior. The SQLite store ensures that all data is written correctly to disk—see “Configuring a SQLite Store’s Save Behavior” (page 133).
Remedy: First determine whether the time taken to save will be noticeable to the user. This is typically likely to be the case only if you configure your application to frequently save automatically—for example, after every edit that the user makes. First, consider changing the store’s save behavior (switch off full sync). Then consider saving data only after a set period (for example, every 15 seconds) instead of after every edit. If necessary, consider choosing a different store—for example, the binary store.
Cannot save documents because entity is null Problem: You have Core Data document-based application that is unable to save. When you try to save the
document you get an exception:
Exception raised during posting of notification. Ignored. exception: Cannot perform operation since entity with name 'Wxyz' cannot be found Cause: This error is emitted by an instance of NSObjectController (or one of its subclasses) that is set in Entity mode but can’t access the entity description in the managed object model associated with the entity name specified in Interface Builder. In short, you have a controller in entity mode with an invalid entity name.
Remedy: Select in turn each of your controllers in Interface Builder, and press Command-1 to show the inspector.
For each controller, ensure you have a valid entity name in the "Entity Name" field at the top.
Exception generated in retainedDataForObjectID:withContext.
Problem: You add an object to a context. When you try to save the document you get an error that looks like