Методы -primitiveValueForKey:
и -setPrimitiveValue:forKey:
в основном используются Core Data.В частности, 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
, если вы хотите, чтобы 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 (или даже код вне -awakeFromInsert
и -awakeFromFetch
).Но это позволяет мне получить базовое хранилище для свойства "name" без встраивания буквенных строк в мой код и с использованием реальных типов.