开发者

How to do perfect KVO for NSManagedObject?

Pe开发者_如何学JAVArfect KVO here includes two parts: add observer correctly and remove observer correctly.

The story:

  1. I use one UITableViewCell(cell) to display one NSManagedObject(object).
  2. Each object has some dynamic properties that need observing by its cell.
  3. Not all objects have the same set of observed properties. I add key path observers selectively like this:

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

  4. Object could be deleted. I must remove observers when object is deleted. The database is very large and complex so I definitely don't want to register all cells to receive moc notifications like NSManagedObjectContextObjectsDidChangeNotification. But I can accept to add a cell ivar in object if I have to, even though it goes agains good Modle-View-Controller design pattern.

The problem: How can I correctly remove the observer(cell) for all the registered key paths from an object when it is deleted?

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

  1. Where is the best place to put the observer removing code?
  2. How do I determine which key paths to unregister? I can't query its properties after an object is deleted — it will cause unfulfillable faults, so I can't write code like this:

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

and I can't either blindly remove observer for unregistered key path — exceptions(Cannot remove an observer for the key path "thumbnail_picture" from because it is not registered as an observer.) will be thrown up.


an0,

There is an NSManagedObject method just for doing deletion timed functions: -prepareForDeletion.

Its documentation claims: "You can implement this method to perform any operations required before the object is deleted, such as custom propagation before relationships are torn down, or reconfiguration of objects using key-value observing."

You could also look at using: -willTurnIntoFault and -didTurnIntoFault. But I think you'll be happier using -prepareForDeletion.

Andrew

P.S. This method is documented in the class reference. I respectfully suggest that you save time by reading the documentation.


The main problem implementing KVO here is that you don't know when the object is getting deleted , at least not outside the NSManagedObject subclass, What you could really do is create a generic delegate on a subclass of NSManagedObject and override its didChangeValueForKey: 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


I believe the mistake is in step 1. Cells should be designed to display different objects. Cells are simply views with labels that can show anything. Tables are optimised to reuse the same cells for different data objects. In your VC create a configureCellWithEvent, configureCellWithVenue methods etc. then you can dequeue a cell of generic identifier and pass it to these methods. Then you likely won’t even have the issue of when to add remove observers because cells shouldn't have object observers.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜