Tracking object changes with notifications

From EOFWiki
Jump to: navigation, search

Contents

Code

#import <Foundation/Foundation.h>
#import <EOControl/EOControl.h>
 
 
@interface PermanentGlobalID : EOTemporaryGlobalID
@end
 
@implementation PermanentGlobalID : EOTemporaryGlobalID
 
- (BOOL) isTemporary
{
   return( NO);
}
 
@end
 
 
@interface NotificationLogger : NSObject
@end
 
@implementation NotificationLogger
 
+ (void) logNotification:(NSNotification *) notification
{
   NSLog( @"%@", notification);
}
@end
 
 
int main (int argc, const char * argv[])
{
   NSAutoreleasePool   *pool;
   EOEditingContext    *context;
   NSMutableString     *obj;
   NSMutableString     *obj2;
   EOGlobalID          *gid;
 
   pool = [NSAutoreleasePool new];
 
   [[NSNotificationCenter defaultCenter] addObserver:[NotificationLogger class]
                                            selector:@selector( logNotification:)
                                                name:nil
                                              object:nil];
 
   context = [[EOEditingContext new] autorelease];
 
   obj = [[@"VfL Bochum 1848" mutableCopy] autorelease];
   gid = [[PermanentGlobalID new] autorelease];
   [context recordObject:obj
                globalID:gid];
 
   NSLog( @"A) %d insertedObjects, %d registeredObjects, %d updatedObjects",
         [[context insertedObjects] count], [[context registeredObjects] count], [[context updatedObjects] count]);
 
   [obj willChange];
   [obj appendString:@"!"];
 
   NSLog( @"B) %d insertedObjects, %d registeredObjects, %d updatedObjects",
         [[context insertedObjects] count], [[context registeredObjects] count], [[context updatedObjects] count]);
 
   obj2 = [[@"Mulle kybernetiK" mutableCopy] autorelease];
   [context insertObject:obj2];
 
   NSLog( @"C) %d insertedObjects, %d registeredObjects, %d updatedObjects",
         [[context insertedObjects] count], [[context registeredObjects] count], [[context updatedObjects] count]);
 
   [obj2 willChange];
   [obj2 appendString:@"!"];
 
   NSLog( @"D) %d insertedObjects, %d registeredObjects, %d updatedObjects",
         [[context insertedObjects] count], [[context registeredObjects] count], [[context updatedObjects] count]);
 
   [pool release];
   return( 0);
}

Comment

The EOEditingContext will send out NSNotifications to reflect the changes made to the objects. It's crucial to understand that the information contained in the userInfo of the NSNotification is different from what you see in the insertedObjects, deletedObjects and updatedObjects lists. The information in the userInfo shows only the changes (diff) between the current state and the last notification.

A freshly recorded object shows up in the list of registered objects (as before), but no notifications are generated yet (Output A).

When the object is changed and willChange is called two NSNotifications are generated by the EOEditingContext (see Note: for technicalities). One shows the edit action by EOGlobalID and one by object. Usually one uses the EOObjectsChangedInEditingContextNotification to observe the EOEditingContext and ignores the EOObjectsChangedInStoreNotification.

Following the output (C) the insert shows up in the notification and also finally the edit of this object (D). Contrary to the behaviour of insertedObjects et al., modifications to inserted objects do appear in the updated and deleted lists of the NSNotification's userInfo.

Output

A) 0 insertedObjects, 1 registeredObjects, 0 updatedObjects
NSConcreteNotification 0x115190 {name = EOObjectsChangedInStoreNotification; object = <EOEditingContext: 0x1063f0>; userInfo = {
    deleted = ();
    inserted = ();
    invalidated = ();
    updated = ( <PermanentGlobalID 0x109410 (hash=0xA0045FE9)> );
}}
NSConcreteNotification 0x115190 {name = EOObjectsChangedInEditingContextNotification; object = <EOEditingContext: 0x1063f0>; userInfo = {
    deleted = ();
    inserted = ();
    invalidated = ();
    updated = ( "VfL Bochum 1848!");
}}


B) 0 insertedObjects, 1 registeredObjects, 1 updatedObjects
NSConcreteNotification 0x115190 {name = EOObjectsChangedInStoreNotification; object = <EOEditingContext: 0x1063f0>; userInfo = {
    deleted = ();
    inserted = ( <EOTemporaryGlobalID 0x1065a0 (hash=0x59DFDAAE)> );
    invalidated = ();
    updated = ();
}}
NSConcreteNotification 0x115190 {name = EOObjectsChangedInEditingContextNotification; object = <EOEditingContext: 0x1063f0>; userInfo = {
    deleted = ();
    inserted = ( "Mulle kybernetiK" );
    invalidated = ();
    updated = ();
}}


C) 1 insertedObjects, 2 registeredObjects, 1 updatedObjects
NSConcreteNotification 0x115190 {name = EOObjectsChangedInStoreNotification; object = <EOEditingContext: 0x1063f0>; userInfo = {
    deleted = ();
    inserted = ();
    invalidated = ();
    updated = ( <EOTemporaryGlobalID 0x1065a0 (hash=0x59DFDAAE)> );
}}
NSConcreteNotification 0x115190 {name = EOObjectsChangedInEditingContextNotification; object = <EOEditingContext: 0x1063f0>; userInfo = {
    deleted = ();
    inserted = ();
    invalidated = ();
    updated = ( "Mulle kybernetiK!" );
}}


D) 1 insertedObjects, 2 registeredObjects, 1 updatedObjects

Note

It's important to understand how the notifications are triggered. Usually the EOEditingContext does not send any notifications until it receives a processRecentChanges message. This method is called by insertedObjects and friends, so the debugging output in this case is necessary to trigger the notification.


In Coalesced object change notifications this will be examined in a bit more detail.

Personal tools