Какой смысл -primitiveValueForKey :? - PullRequest
2 голосов
/ 10 ноября 2010

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

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

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

1 Ответ

23 голосов
/ 18 ноября 2010

Методы -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" без встраивания буквенных строк в мой код и с использованием реальных типов.

...