2010-11-10 4 views
2

-setPrimitiveValue:forKey: не будет вызывать уведомления KVO. Но в моем мозгу KVO имеет смысл только тогда, когда что-то меняется. Но как можно что-то изменить, когда я получаю доступ к нему только для чтения?В чем смысл -primitiveValueForKey :?

-primitiveValueForKey: получает объект только за некоторый ключ. Но это не изменит его. Итак, почему это могло быть причиной KVO-уведомлений при использовании -valueForKey:?

(Конечно, есть точка, но я не вижу его.)

+1

Пожалуйста, отметьте ответные вопросы в соответствии с ответом, или если вы что-то не поняли, пожалуйста, задайте в комментариях ответы. Благодаря! –

ответ

23

В -primitiveValueForKey: и -setPrimitiveValue:forKey: методы в основном используются Core Data. В частности, Core Data не просто нужно знать, когда вы собираетесь изменять атрибут; он должен знать, когда вы собираетесь получить к нему доступ, так что он может реализовать сбои.

Таким образом, данные ядра добавляют -{will,did}AccessValueForKey: методы для использования в геттерах, так же как методы -{will,did}ChangeValueForKey: существуют для использования в сеттерах в качестве крючков KVO.

Однако есть еще одна морщина: Core Data фактически управляет базовым хранилищем смоделированных свойств для вас. Поэтому вам нужно каким-то образом манипулировать этим базовым хранилищем в пределах барьерами, установленными методами -{will,did}{Access,Change}ValueForKey:. Вот где -primitiveValueForKey: и -setPrimitiveValue:forKey: приходят в

Поэтому стандартный шаблон для реализации методов получения и установки ядра данных, до существования @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 если вы хотите основные данные, чтобы создать этот материал для вас во время выполнения:

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

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

@implementation Person 
@dynamic name; 
@end 

есть некоторые Ситу но там, где вы все еще хотите манипулировать базовым хранилищем без KVO или сбой при стрельбе. Таким образом, ядро ​​данных обеспечивает новый способ, чтобы получить на это, а также построены вокруг объявлений свойств и автоматического синтеза:

// 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; это не то, что код вне Личности (или даже действительно код вне -awakeFromInsert и -awakeFromFetch) должен касаться. Но это позволяет мне получить базовое хранилище для свойства «name» без вложения литеральных строк в мой код и с использованием реальных типов.