Core Data Release Notes

This article summarizes some of the new features and changes in functionality in Core Data on Mac OS X v10.5 (Leopard).

Contents:

Taking Advantage of New Features: Linking
Store Versioning and Migration
Persistent Store API
64-bit and Garbage Collection
NSManagedObject
Fetching
Performance and Multi-Threading
Performance Analysis
Deleting Objects
SQLite Store Options
NSErrorMergePolicy and Optimistic Locking Records
Managed Object Context, save:, and commitEditing


Taking Advantage of New Features: Linking

Core Data provides a number of major new features and enhancements on Mac OS X v10.5. You can take advantage of these on Mac OS X v10.5 while still maintaining backwards compatibility with Mac OS X v10.4 provided that you link your application appropriately.

There are two ways you can build (on Mac OS X v10.5) a project that runs on both Mac OS X v10.4 and Mac OS X v10.5:

  1. Build a Tiger project against the Mac OS X v10.4 SDK.

  2. Build a Leopard project against the Mac OS X v10.5 SDK and set the "Mac OS X Deployment Target" to Mac OS X v10.4.

The first option is what most developers do by default. This means, however, that even on Mac OS X v10.5 the application runs as a Mac OS X v10.4 application and cannot use new features or exclusive bug fixes. To take advantage of the new features and bug fixes, you must build your project against the Mac OS X v10.5 SDK and set the "Mac OS X Deployment Target" to Mac OS X v10.4.

Store Versioning and Migration

One of the major new Leopard features is an architecture to support versioning and migration—see Core Data Model Versioning and Data Migration Programming Guide for more details.

Persistent Store API

One of the major new Leopard features is a way that you can create your own persistent store type. You use the new NSPersistentStore and NSAtomicStore classes—see Atomic Store Programming Topics for more details. Persistent stores in general are discussed in Persistent Stores and Using Persistent Stores .

64-bit and Garbage Collection

On Mac OS X v10.5, Core Data is fully 64-bit compliant and fully GC-compliant.

NSManagedObject

On Mac OS X v10.5, NSManagedObject is a class cluster. In practice, this should typically make no difference to the code you write. It does mean, however, that you must use the proper Cocoa patterns if you override an initializer—that is, you must ensure that you set self to the return value from invocation of super’s implementation, as shown in the following example:

- (id)initWithEntity:(NSEntityDescription*)entityinsertIntoManagedObjectContext:(NSManagedObjectContext*)context
{
    if (self = [super initWithEntity:entity insertIntoManagedObjectContext:context])
    {
        // perform additional initialization
    }
    return self;
}

primitiveValueForKey: no longer supports unmodeled properties—there is no support for undefined keys.

NSManagedObject uses dynamic class generation to support the Objective-C 2 properties feature (see “Objective-C 2 Support” ) by automatically creating a subclass of your class appropriate for your entity. This is also typically transparent to you, however whereas NSManagedObject ’s class method returns your class, the Objective-C function object_getClass returns the dynamically-generated class.

As a class cluster, NSManagedObject 's alloc /initWithEntity:insertIntoManagedObjectContext: pair will always return an instance of correct class for the entity you pass as the parameter. The dynamically-generated subclass will be based on the class specified by the entity, so specifying a custom class in your model will supersede the class passed to alloc .

Transformable Attributes

There's a new "transformable" type for NSManagedObject attributes that allows you more easiliy support attribute types that Core Data doesn't support natively. You access an attribute as a non-standard type, but behind the scenes Core Data uses an instance of NSValueTransformer to convert the attribute to and from an instance of NSData . Core Data then stores the data instance to the persistent store.

If you don't specify a transformer, transformable attributes to use keyed archiving (NSKeyedUnarchiveFromDataTransformerName ). Note that this is a change from pre-release Leopard seeds which instead used serial archiving.

For more details, see Non-Standard Attributes .

Objective-C 2 Support

You can use Objective-C declared properties (see Properties ) in custom subclasses of NSManagedObject .

Accessor methods

On Mac OS X v10.5, Core Data will dynamically generate extremely efficient public and primitive get and set attribute accessor methods and relationship accessor methods for managed object classes. These are described in detail in Managed Object Accessor Methods , but this is a summary of the most important points:

Subclassing

If you have two subclasses of NSManagedObject , and the parent class implements a dynamic property, and its subclass (the grandchild of NSManagedObject ) overrides the methods for the property, those overrides cannot call super.

@interface Parent : NSManagedObject
@property(retain) NSString* foo;
@end
 
@implementation Parent
@dynamic foo;
@end
 
@interface Child : Parent
@end
 
@implementation Child
- (NSString*) foo
{
    // this throws: selector not found
    return super.foo;
}
@end

Fetching

When you create a fetch request, you can use setRelationshipKeyPathsForPrefetching: to specify key paths for relationships that should be fetched with the target entity. There are numerous other new configuration options for fetch requests—see NSFetchRequest for full details.

Performance and Multi-Threading

The new API for NSFetchRequest can be extremely helpful in working with data between threads. For example, you can configure a fetch request to return object IDs but exclude the row data (and update the row cache)—this can be useful if you're just going to pass those object IDs from a background thread to another thread. You can also pre-fetch relationships (which avoids the issue described in “Pre-fetching” in Performance ) and pre-populate managed objects (that is, disable lazy initialization—which avoids the issue described in “Batch faulting” in Performance ).

On Mac OS X v10.5, executeFetchRequest:error: intrinsically scales its behavior appropriately for the hardware and work load. If necessary, the Core Data will create additional private threads to optimize fetching performance. You will not now improve absolute fetching speed by creating background threads (although it may still be appropriate to fetch in a background thread for enhanced responsiveness—that is, to prevent your application from blocking).

Core Data now tries to optimize stack tear down (destruction of the persistent store coordinator, persistent stores, and so on). When a stack is torn down, the dealloc method of the component objects may not be called. You should therefore not do resource cleanup (such as removal of temporary files) in a dealloc method, instead you should invalidate resources when they are no longer needed (for a discussion of this subject as it pertains to garbage collection, see Adopting Garbage Collection in Garbage Collection Programming Guide ).

Changes have been made to the merge policies to improve robustness and avoid resurrecting certain objects. On Mac OS X v10.4, there were issues with objects that have with relationships to deleted objects, when the delete rules would have cascaded had all the changes been made in the same context. On Mac OS X v10.5, merge policies handle delete propagation cascades correctly even between processes with disparate updates.

Performance Analysis

Core Data now provides support for various dtrace probes, which can also be used with Instruments—see “Analyzing Performance” in Performance for more information.

Deleting Objects

On Mac OS X v10.4, you could not call deleteObject: in a set accessor method; on Mac OS X v10.5 you can.

On Mac OS X v10.4, you could not delete an object if it was a fault that could not be fulfilled (that is, already deleted by another context or process). On Mac OS X v10.5, you can always delete faults to missing records.

On Mac OS X v10.5, Core Data won’t let you save the object graph if in the validation stage it contains a reference to a deleted object. For example, during a save operation Core Data will generate a deny error if a deleted object has a relationship to another object. This may happen especially if you haven’t specified a relationship without an inverse, or if after propagating deletions you add a reference to a deleted object. This is a change in behavior from Mac OS X v10.4 (Mac OS X v10.4 would not generate deny errors). Note that if you manually perform validation, you may need to call processPendingChanges first so that deletions and other coalesced operations cascade completely to purge any references to pending deletions from the graph.

SQLite Store Options

On Mac OS X v10.4, there are only two settings to control the way in which data in a SQLite-based store is written to disk. In order to provide finer granularity of control over the tradeoff between performance and reliability, on Mac OS X v10.5 Core Data uses two independent pragmas to control these options.

Note that the default fsync behavior on Tiger was fcntl(F_FULLFSYNC) but on Leopard it is now a standard fsync . (This affects all SQLite databases on Leopard, not just Core Data.) The pragma allows you to toggle this value. See “Configuring a SQLite Store’s Save Behavior” in Persistent Stores for a full discussion.

In addition, the SQLite store now supports:

NSErrorMergePolicy and Optimistic Locking Records

The NSErrorMergePolicy policy causes a save to fail if there are any merge conflicts (see “Conflict Detection and Optimistic Locking” and “Conflict Resolution” in Change Management ). In the case of failure, the save: method returns with an error with a user info dictionary that contains the key @"conflictList" ; the corresponding value is an array of conflict records.

On Mac OS X v10.4, all relationship values in the records are managed objects; on Mac OS X v10.5, all relationship values in the records to be objectIDs. This change is backwards binary compatible, so this only affects compiled on Mac OS X v10.5 and using the NSErrorMergePolicy to perform some kind of custom recovery.

Managed Object Context, save:, and commitEditing

The behavior of NSManagedObjectContext ’s save: method has changed in Mac OS X v10.5. On Mac OS X v10.4, the save: method erroneously caused bound text views to commit their pending edits ; on Mac OS X v10.5 this error has been fixed.

This means that, for example, in Core Data non-document template based applications linked on or after Mac OS X v10.5, to replicate the behavior of a Mac OS X v10.4 application, the application delegate needs to send the managed object context a commitEditing message when saving.

The CoreData application template provided with Xcode includes an application delegate that implements some basic Core Data and application functionality, including a save action. The implementation of the saveAction: method is simple—it just tells the delegate's managed object context to save. For user interfaces created with Cocoa Bindings and linked on Mac OS X v10.5, this has the effect of discarding editing before doing the actual save. For applications linked on Mac OS X v10.4, this behavior triggered a bug where bound text views would have their pending edits committed instead of discarded.

This has been fixed for applications linked on or after Mac OS X v10.5. However, this does mean that if you want pending edits in bound text views to be committed during a save you need to modify the saveAction: method to first call [[self managedObjectContext] commitEditing] (or use the commitEditingWithDelegate:didCommitSelector:contextInfo: variant) before saving. Otherwise the pending edits will be discarded.





© 2007 Apple Inc. All Rights Reserved. (Last updated: 2007-12-11)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.