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
只将NSNumbers
, NSDates
, NSDatas
和NSStrings
作为属性的事实。
但是,这可能不是最好的方法。 既然你想在foo
属性的值发生变化的时候发生什么,为什么不用一个关键值观察来观察呢? 在这种情况下,这听起来像“KVO的路要走”。
以下是我如何在Photo : NSManagedObject
的id
属性上执行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]; }