-setPrimitiveValue:forKey:
不会触发 KVO 通知。但在我的脑海中,KVO 只有在发生变化时才有意义。但是,当我仅访问它以进行读取时,如何更改某些内容?
-primitiveValueForKey:
只获取某个键的对象。但它不会修改它。那么为什么在使用时会/可能会导致 KVO 通知-valueForKey:
?
(当然有一点,但我还没有看到。)
-setPrimitiveValue:forKey:
不会触发 KVO 通知。但在我的脑海中,KVO 只有在发生变化时才有意义。但是,当我仅访问它以进行读取时,如何更改某些内容?
-primitiveValueForKey:
只获取某个键的对象。但它不会修改它。那么为什么在使用时会/可能会导致 KVO 通知-valueForKey:
?
(当然有一点,但我还没有看到。)
和方法主要由 Core Data 使用-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:
这就是为什么在 and 存在之前实现核心数据 getter 和 setter 的标准模式@property
看起来@dynamic
像这样:
// 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
当然,现在你可以声明一个属性并定义它,就@dynamic
好像你希望 Core Data 在运行时为你生成这些东西一样:
// 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 之外的代码(甚至是真正的 and 之外的代码-awakeFromInsert
)-awakeFromFetch
应该触及的东西。但它确实让我获得了“名称”属性的底层存储,而无需在我的代码中嵌入文字字符串,并且使用真实类型。