How to make perfect KVO for NSManagedObject?

The ideal KVO here includes two parts: correctly add an observer and correctly remove an observer.

Story:

  • I use one UITableViewCell (cell) to display a single NSManagedObject (object).
  • Each object has some dynamic properties that must be observed in its cell.
  • Not all objects have the same set of observable properties. I add key path watchers selectively as follows:

    if (object.thumbnail_pic_url) [object addObserver: cell forKeyPath: @ "thumbnail_picture": 0 context: NULL];

  • The object can be deleted. I have to remove the watchers when the object is deleted. The database is very large and complex, so I definitely don’t want to register all cells to receive moc notifications, such as NSManagedObjectContextObjectsDidChangeNotification. But I can agree to add an ivar cell to the object, if necessary, even if it again matches the good Modle-View-Controller design pattern.

Problem: how can I correctly remove the observer (cell) for all registered paths of the key to the object when it is deleted?

In fact, this is a big problem that can be divided into two small problems:

  • Where is the best place to place the observer deletion code?
  • How to determine which key ways to unregister? I cannot request its properties after deleting the object - this will cause unexecutable errors, so I cannot write such code:

    if (object.thumbnail_pic_url) [object removeObserver: cell forKeyPath: @ "thumbnail_picture"];

and I can’t either blindly delete the observer for the unregistered key path - exceptions (the observer for the thumbnail_picture key path cannot be deleted because it is not registered as an observer.) will be reset.

+7
source share
3 answers

AN0,

There is an NSManagedObject method only for performing temporary removal functions: -prepareForDeletion.

Its documentation states: "You can implement this method to perform any operations required before deleting the object, for example, user distribution before the relationship is demolished, or reconfiguring the objects using key monitoring."

You can also look at using: -willTurnIntoFault and -didTurnIntoFault. But I think you will be happier to use -prepareForDeletion.

Andrew

PS This method is described in the class reference. I respectfully suggest that you save time by reading the documentation.

+3
source

The main problem with KVO implementation here is that you do not know when the object is deleted, at least not outside the NSManagedObject subclass. What you really could do is create a common delegate in a subclass of NSManagedObject and override it with hasChangeValueForKey: method

// DataObservingManagedObject.h #import <Foundation/Foundation.h> #import <MMRecord/MMRecord.h> @protocol DataObservingDelegate <NSObject> -(void)valueChangedForKey:(NSString*)key andValue:(id)value; @end @interface DataObservingManagedObject : NSManagedObject @property(nonatomic,weak)id<UserStatusDelegate> changeDelegate; @end //DateObservingManagedObject.m #import "DateObservingManagedObject.h" @implementation DateObservingManagedObject @synthesize changeDelegate=_changeDelegate; -(void)didChangeValueForKey:(NSString *)key{ [self.changeDelegate valueChangedForKey:key andValue:[self valueForKey:key]]; } @end 
0
source

I believe that the error is in step 1. Cells should be designed to display different objects. Cells are simply tagged views that can show anything. Tables are optimized for reusing the same cells for different data objects. In your VC, create configureCellWithEvent, configureCellWithVenue, etc. methods. Then you can remove the common identifier cell from the queue and pass it to these methods. Then you probably will not even have a question about when to add delete observers, because there should not be object observers in the cells.

0
source

All Articles