Core-Data中的自定义setter方法

And*_*ing 68 setter core-data objective-c

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

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

- (void)setFoo: (NSObject *)inFoo {
    [super setFoo: inFoo];
    [self updateStuff];
}
Run Code Online (Sandbox Code Playgroud)

然后我在调用时收到编译器警告super.

或者,如果我这样做:

- (void)setFoo: (NSObject *)inFoo {
    [super setValue: inFoo forKey: inFoo];
    [self updateStuff];
}
Run Code Online (Sandbox Code Playgroud)

然后我最终陷入无限循环.

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

Dav*_*ong 103

根据文档,它是:

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

这是当然的,忽略的事实NSManagedObjects只是想NSNumbers,NSDates,NSDatas,和NSStrings为属性.

但是,这可能不是最好的方法.由于您希望在foo属性值发生变化时发生某些事情,为什么不用Key Value Observing观察它呢?在这种情况下,它听起来像"KVO的方式去".


ma1*_*w28 19

这是我在ida 的属性上做KVO 的方式Photo : NSManagedObject.如果照片的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
}
Run Code Online (Sandbox Code Playgroud)

  • 从apple的文档中,你应该在"awakeFromFetch"和"awakeFromInsert"上调用super (3认同)

Mar*_*ger 17

I think there is a slight mistake: use

 [self setPrimitiveValue:inFoo forKey:@"foo"];
Run Code Online (Sandbox Code Playgroud)

instead of

 [self setPrimitiveFoo:inFoo];
Run Code Online (Sandbox Code Playgroud)

this works for me.

  • 不要使用 - (void)dealloc取消注册,取消注册 - (void)willTurnIntoFault中的观察.否则,当对象变成故障时,您将收到不必要的通知.插入的新对象不会获得 - (void)awakeFromFetch消息.use - (void)awakeFromInsert. (7认同)

mal*_*hal 7

以下是在.m中覆盖NSManagedObject属性(不破坏KVO)的Apple方法:

@interface Transaction (DynamicAccessors)
- (void)managedObjectOriginal_setDate:(NSDate *)date;
@end

@implementation Transaction
@dynamic date;

- (void)setDate:(NSDate *)date
{
    // invoke the dynamic implementation of setDate (calls the willChange/didChange for you)
    [self managedObjectOriginal_setDate:(NSString *)date;

    // your custom code
}
Run Code Online (Sandbox Code Playgroud)

managedObjectOriginal_propertyName是一个内置的魔术方法,你只需添加定义.如本页底部所示,macOS 10.12,iOS 10.0,tvOS 10.0和watchOS 3.0中的核心数据有什么新功能