Core-Data中的自定义setter方法

我需要为NSManagedObject子类中的字段(我们将它称为foo )编写自定义setter方法。 foo在数据模型中定义,Xcode分别在.h和.m文件中自动生成@dynamic@dynamic字段。

如果我这样写我的二传手:

 - (void)setFoo: (NSObject *)inFoo { [super setFoo: inFoo]; [self updateStuff]; } 

然后我得到一个编译器警告在super的调用。

或者,如果我这样做:

 - (void)setFoo: (NSObject *)inFoo { [super setValue: inFoo forKey: inFoo]; [self updateStuff]; } 

那么我将无限循环地结束。

那么,为NSManagedObject的子类编写自定义setter的正确方法是什么?

根据文件 ,这将是:

 - (void) setFoo:(NSObject *)inFoo { [self willChangeValueForKey:@"foo"]; [self setPrimitiveValue:inFoo forKey:@"foo"]; [self didChangeValueForKey:@"foo"]; } 

当然,这是忽略NSManagedObjects只将NSNumbersNSDatesNSDatasNSStrings作为属性的事实。

但是,这可能不是最好的方法。 既然你想在foo属性的值发生变化的时候发生什么,为什么不用一个关键值观察来观察呢? 在这种情况下,这听起来像“KVO的路要走”。

以下是我如何在Photo : NSManagedObjectid属性上执行KVO。 如果照片的ID改变,则下载新照片。

 #pragma mark NSManagedObject - (void)awakeFromInsert { [self observePhotoId]; } - (void)awakeFromFetch { [self observePhotoId]; } - (void)observePhotoId { [self addObserver:self forKeyPath:@"id" options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:NULL]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"id"]) { NSString *oldValue = [change objectForKey:NSKeyValueChangeOldKey]; NSString *newValue = [change objectForKey:NSKeyValueChangeNewKey]; if (![newValue isEqualToString:oldValue]) { [self handleIdChange]; } } } - (void)willTurnIntoFault { [self removeObserver:self forKeyPath:@"id"]; } #pragma mark Photo - (void)handleIdChange { // Implemented by subclasses, but defined here to hide warnings. // [self download]; // example implementation } 

我觉得有一个小小的错误:使用

  [self setPrimitiveValue:inFoo forKey:@"foo"]; 

代替

  [self setPrimitiveFoo:inFoo]; 

这对我有用。

以下是你如何做1-n(和我认为nm)的关系:

假设关系名称被称为“学生”的对象称为“学生”。

首先,您需要为NSMutableSet定义原始访问器方法。 Xcode不会自动为你生成这些。

 @interface School(PrimitiveAccessors) - (NSMutableSet *)primitiveStudents; @end 

接下来你可以定义你的访问器方法。 这里我要重写setter。

 - (void)addStudentsObject:(Student *)student { NSSet *changedObjects = [[NSSet alloc] initWithObjects:&student count:1]; [self willChangeValueForKey:@"students" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects]; [[self primitiveStudents] addObject:value]; [self didChangeValueForKey:@"students" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects]; }