如何为NSManagedObject做完美的KVO?

时间:2011-09-29 22:50:16

标签: ios core-data key-value-observing nsmanagedobject

完美KVO包括两个部分:正确添加观察者并正确删除观察者。

故事:

  1. 我使用一个UITableViewCell(单元格)来显示一个NSManagedObject(对象)。
  2. 每个对象都有一些动态属性,需要通过其单元格进行观察。
  3. 并非所有对象都具有相同的观察属性集。我有选择地添加关键路径观察器:

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

  4. 可以删除对象。删除对象时,我必须删除观察者。数据库非常庞大和复杂,所以我绝对不想注册所有单元格来接收moc通知,如NSManagedObjectContextObjectsDidChangeNotification。但是如果必须的话,我可以接受在对象中添加一个单元格ivar,即使它再次成为好的Modle-View-Controller设计模式。

  5. 问题:在删除对象时,如何正确删除对象中所有已注册密钥路径的观察者(单元格)?

    事实上,这是一个很大的问题,可以分为两个小问题:

    1. 观察者删除代码的最佳位置在哪里?
    2. 如何确定要取消注册的关键路径?在删除对象后我无法查询其属性 - 这将导致无法填充的错误,因此我无法编写如下代码:

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

    3. 我无法盲目地删除未注册的密钥路径的观察者 - 异常(无法删除密钥路径“thumbnail_picture”的观察者,因为它未被注册为观察者。)将被抛出。

3 个答案:

答案 0 :(得分:3)

AN0,

有一个NSManagedObject方法只用于执行删除定时函数:-prepareForDeletion。

其文档声称:“您可以实现此方法以在删除对象之前执行所需的任何操作,例如在关系被拆除之前进行自定义传播,或使用键值观察重新配置对象。”

您还可以使用:-willTurnIntoFault和-didTurnIntoFault。但我认为使用-prepareForDeletion会更快乐。

安德鲁

P.S。此类方法记录在类引用中。我恭敬地建议您通过阅读文档来节省时间。

答案 1 :(得分:0)

在这里实现KVO的主要问题是你不知道对象什么时候被删除,至少不在NSManagedObject子类之外。你真正要做的是在NSManagedObject的子类上创建泛型委托并覆盖它的didChangeValueForKey:方法

  // 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

答案 2 :(得分:0)

我认为错误在于步骤1。单元格应设计为显示不同的对象。单元格只是带有可显示任何内容的标签的视图。对表进行了优化,以将相同的单元格用于不同的数据对象。在您的VC中,创建一个configureCellWithEvent,configureCellWithVenue方法等,然后您可以使具有通用标识符的单元出队,并将其传递给这些方法。这样一来,您甚至根本不会出现何时添加移除观察者的问题,因为单元格不应该包含对象观察者。