什么是-primitiveValueForKey:?

时间:2010-11-10 17:09:06

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

-setPrimitiveValue:forKey:不会触发KVO通知。但在我的大脑中,KVO只有在发生变化时才有意义。但是当我只是为了阅读而访问它时,怎么能改变呢?

-primitiveValueForKey:只获取某个键的对象。但它不会修改它。那么为什么在使用-valueForKey:时会导致KVO通知呢?

(当然有一点,但我还没看到。)

1 个答案:

答案 0 :(得分:23)

-primitiveValueForKey:-setPrimitiveValue:forKey:方法主要由Core Data使用。特别是,Core Data不仅需要知道何时修改属性;它需要知道你什么时候才能访问它,所以它可以实现错误。

因此,核心数据添加-{will,did}AccessValueForKey:方法以在getter中使用,就像-{will,did}ChangeValueForKey:方法存在用于setter充当KVO钩子一样。

然而,还有另一个问题:Core Data实际上也为您管理建模属性的底层存储。因此,您需要一些方法来操纵中构建的-{will,did}{Access,Change}ValueForKey:方法所构建的障碍。这就是-primitiveValueForKey:-setPrimitiveValue:forKey:进来的地方。

这就是为什么在@property@dynamic存在之前实现Core Data getter和setter的标准模式如下所示:

// Person.m
#import "Person.h"

@implementation Person

- (NSString *)name {
    [self willAccessValueForKey:@"name"];
    NSString *value = [self primitiveValueForKey:@"name"];
    [self didAccessValueForKey:@"name"];
}

- (void)setName:(NSString *)value {
    [self willChangeValueForKey:@"name"];
    [self setPrimitiveValue:value forKey:@"name"];
    [self didChangeValueForKey:@"name"];
}

@end

当然,如果您希望Core Data在运行时为您生成这些内容,您可以声明一个属性并将其定义为@dynamic

// Person.h
@interface Person : NSManagedObject
@property (nonatomic, readwrite, copy) NSString *name;
@end

// Person.m
#import "Person.h"

@implementation Person
@dynamic name;
@end

但是,在某些情况下,您仍然希望操纵底层存储而不使用 KVO或故障触发。因此,Core Data也提供了一种新的方法,也可以围绕属性声明和自动综合构建:

// Person.h
@interface Person : NSManagedObject
@property (nonatomic, readwrite, copy) NSString *name;
@end

// Person.m
#import "Person.h"

@interface Person ()
@property (nonatomic, readwrite, copy) NSString *primitiveName;
@end

@implementation Person
@dynamic name;
@dynamic primitiveName;
@end

请注意,我将类继续放在.m文件中;这不是Person之外的代码(甚至是-awakeFromInsert-awakeFromFetch之外的真正代码)应该触及的东西。但它确实让我得到了“name”属性的底层存储,而没有在我的代码中嵌入文字字符串,并使用真实类型。