Core-Data中的自定义setter方法

时间:2010-06-04 05:51:21

标签: objective-c core-data setter

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

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

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

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

或者,如果我这样做:

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

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

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

6 个答案:

答案 0 :(得分:102)

根据the documentation,它是:

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

当然,这忽略了NSManagedObjects只想要NSNumbersNSDatesNSDatasNSStrings作为属性这一事实。

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

答案 1 :(得分:19)

以下是我在id的{​​{1}}属性上执行KVO的方式。如果照片的ID发生变化,请下载新照片。

Photo : NSManagedObject

答案 2 :(得分:17)

我认为有一个小错误: 使用

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

而不是

 [self setPrimitiveFoo:inFoo];

这适合我。

答案 3 :(得分:6)

以下是在.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
}

managedObjectOriginal_propertyName是一个内置的 magic 方法,您只需添加其定义即可。如本页底部所示What's New in Core Data in macOS 10.12, iOS 10.0, tvOS 10.0, and watchOS 3.0

答案 4 :(得分:1)

有一个非常方便的 Xcode Snippets 菜单(Xcode 12 右上角有一个 + 按钮),其中包含用于覆盖许多常见 Core Data 代码的很棒的片段,包括用于对象的 KVO 兼容访问器-类型(getter + setter)。

答案 5 :(得分:0)

这里是你如何做到1-n(我假设n-m)关系:

让我们假设关系名称被称为"学生"在一个名为" School"。

的对象中

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

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

接下来,您可以定义访问者方法。在这里,我将覆盖设置者。

- (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];
}