Subclassing NSAtomicStore
Subclassing NSAtomicStore
- Subject: Subclassing NSAtomicStore
- From: Pierre Molinaro <email@hidden>
- Date: Mon, 28 Jan 2008 17:48:41 +0100
Hi everyone,
I have successfully written a subclass of NSAtomicStore, I met some
difficulties, and I would like to share my solutions with other Cocoa
developers.
The documents I used :
- [1] : Atomic Store Programming Topics (http://developer.apple.com/documentation/Cocoa/Conceptual/AtomicStore_Concepts/Introduction/Introduction.html
)
- [2] : CustomAtomicStoreSubclass sample code (http://developer.apple.com/samplecode/CustomAtomicStoreSubclass/
)
- [3] : HTML Store sample code (http://developer.apple.com/samplecode/HTMLStore/
)
For all sample codes, and for my subclass, I have tracked messages by
adding NSLog (@"%s", __PRETTY_FUNCTION__) at the beginning of every
method.
The first point is the -setIdentifier: method, redefined in both
sample codes : it seems it is never called. Consequently, in [2], -
identifier returns always nil. I have not implemented theses methods
in my subclass.
The second and main point concerns the way for populating the cache
nodes for inserted objects. When a -save: message is sent to a managed
object context, a sequence of messages is sent the subclass of the
atomic store for creating, updating or removing cache nodes ; then a -
save: message is sent for saving cache nodes values. For example, if 2
objects are inserted, 2 updated, and 1 deleted, the sequence is the
following (done with the HTML store example) :
-[ApplicationDelegate saveAction:] -- Message sent by save menu item;
this method sends a -save: message to managed object context.
-[HTMLStore newReferenceObjectForManagedObject:] -- For the first
inserted object
-[HTMLStore newReferenceObjectForManagedObject:] -- For the second
inserted object
-[HTMLStore newCacheNodeForManagedObject:] -- For the first inserted
object
-[HTMLStore updateCacheNode:fromManagedObject:] -- For the first
inserted object (sent by previous method)
-[HTMLStore newCacheNodeForManagedObject:] -- For the second inserted
object
-[HTMLStore updateCacheNode:fromManagedObject:] -- For the second
inserted object (sent by previous method)
-[HTMLStore willRemoveCacheNodes:] [1 node] -- For deleting cache
nodes corresponding to deleted object (here: 1)
-[HTMLStore updateCacheNode:fromManagedObject:] -- For the first
updated object
-[HTMLStore updateCacheNode:fromManagedObject:] -- For the second
updated object
-[HTMLStore save:] -- For saving cache nodes
For every inserted object, a -newReferenceObjectForManagedObject:
message is sent, and then a -newCacheNodeForManagedObject: message. In
both sample codes, the -newCacheNodeForManagedObject: sends an -
updateCacheNode:fromManagedObject: for populating the cache node. For
a to-one relationship, [1] indicates the value in cache node must be
another cache node instance, and for a to-many relationship, a
collection of the related cache nodes. Here the problem : if the first
object refers the second one, its cache node cannot be populated,
since the second cache node is not created yet. In [2], a subclass of
NSAtomicStoreCacheNode is used, perhaps for this reason, and it makes
the code complicated.
I have solved this in a simpler way by the following hint : I have
noticed the -willRemoveCacheNodes is always sent (even if there is no
node to remove), and after all -newCacheNodeForManagedObject:
messages. So, in my subclass of NSAtomic store :
- newCacheNodeForManagedObject: does not populate the cache node, but
inserts it in a collection ;
- willRemoveCacheNodes: enumerates this collection for populating the
cache nodes : I think it is safe since all cache nodes are created.
Here is my code :
- (NSAtomicStoreCacheNode *) newCacheNodeForManagedObject:
(NSManagedObject *) inManagedObject {
NSManagedObjectID * moid = [inManagedObject objectID] ;
NSAtomicStoreCacheNode * newNode = [[NSAtomicStoreCacheNode alloc]
initWithObjectID:moid];
if (mAddedPairs == nil) { // mAddedPairs is an attribute
mAddedPairs = [NSMutableArray new] ;
}
[mAddedPairs addObject:newNode] ;
[mAddedPairs addObject:inManagedObject] ;
return newNode ;
}
- (void) willRemoveCacheNodes:(NSSet *) inCacheNodes {
for (NSUInteger i=0 ; i<[mAddedPairs count] ; i+=2) {
NSAtomicStoreCacheNode * node = [mAddedPairs objectAtIndex:i] ;
NSManagedObject * object = [mAddedPairs objectAtIndex:i+1] ;
[self updateCacheNode:node fromManagedObject:object] ;
}
[mAddedPairs removeAllObjects] ;
//--- Stuff for removed cache nodes
…
}
It would be cleaner the CoreData framework sends after all -
newCacheNodeForManagedObject: messages an -
updateCacheNode:fromManagedObject: message for every created cache
node (or a specific -setNewCacheNode:fromManagedObject: message).
Best Regards
--
Pierre_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden