Что такое Кодирование значения ключа и Наблюдение значения ключа в Objective C?

Может кто-то объяснять простыми словами, что Key-Value-Coding и Key-Value-Observing? Не предоставляйте ссылки на справочный документ Разработчика Apple. Я прошел их. Я ожидаю объяснение в очень простых терминах.

62
задан 16 April 2014 в 06:33

4 ответа

Кодирование значения ключа (KVC) означает получать доступ к свойству или значению с помощью строки.

id someValue = [myObject valueForKeyPath:@"foo.bar.baz"];

, Который мог совпасть с:

id someValue = [[[myObject foo] bar] baz];

Наблюдение значения ключа (KVO) позволяет Вам наблюдать изменения в свойстве или значении.

Для наблюдения свойства с помощью KVO Вы отождествили бы к свойству со строкой; т.е. использование KVC. Поэтому заметный объект должен быть KVC совместимый.

[myObject addObserver:self forKeyPath:@"foo.bar.baz" options:0 context:NULL];
120
ответ дан 31 October 2019 в 13:25

Кодирование значения ключа позволяет Вам выбирать или изменять свойство объекта с помощью строки, во времени выполнения, вместо того, чтобы должным быть написать код, который компилируется в фиксированное свойство от запуска:

NSNumber* foo = [myPopup valueForKey: @"selectedItemIndex"];
[myPopup setValue: @15 forKey: @"selectedItemIndex"];

А хорошим примером для этого является NSTableView на Mac, где можно просто установить идентификатор на каждом столбце таблицы, который соответствует свойству объекта модели, которое он должен отобразить, и затем источник данных просто называет-valueForKey:/-setValue:forKey: с идентификатором столбца, поскольку ключ и значения в значительной степени отображают/устанавливают себя. Вы просто добавляете правые столбцы к табличному представлению в XIB.

наблюдение Значения ключа было добавлено впоследствии и позволяет Вам зарегистрироваться, чтобы быть уведомленными об изменениях, внесенных в другой объект. Вы регистрируете свой интерес путем выполнения:

void*    gMyKVOContext = &gMyKVOContext; // global variable somewhere that guarantees us a unique address that doesn't collide with a subclass's registration for observing the same property

...

[interestingObject addObserver: interestedObject forKeyPath: @"interestingProperty" options: 0 context: gMyKVOContext];

Каждый раз, когда то свойство изменяется,-observeValueForKeyPath:ofObject:change:context: будет назван на объекте, который Вы указали как наблюдатель. Таким образом, Вы реализовали бы это как:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if( context == gMyKVOContext && [keyPath isEqualToString: @"interestingProperty"] )
    {
        // Update UI that shows interestingProperty
    }
    else
        [super observeValueForKeyPath: keyPath ofObject: object change: change context: context];
}

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

, Чтобы сделать свойство заметным, или использовать значение по умолчанию @synthesized реализация при определении его, или если Вы определяете его сами, реализуйте метод set как:

-(void)  setFoo: (int)inFoo
{
    [self willChangeValueForKey: @"foo"];
    _foo = inFoo;
    [self didChangeValueForKey: @"foo"];
}

Затем всегда проходят метод set для изменения его, не изменяйте _foo непосредственно. При связи свойств, которые могли бы противоречить друг другу как вышеупомянутое, хороший способ избежать, чтобы это всегда изменяло их обоих в парах (Вы не можете использовать KVC затем, хотя). Чтобы сделать это, реализуйте объединенный метод set как:

-(void) setFoo: (int)inFoo bar: (int)inBar
{
    [self willChangeValueForKey: @"foo"];
    [self willChangeValueForKey: @"bar"];
    _foo = inFoo;
    _bar = inBar;
    [self didChangeValueForKey: @"bar"];
    [self didChangeValueForKey: @"foo"];
}

Тот путь, оба уведомления отправляются, в то время как свойства находятся в надлежащих состояниях.

12
ответ дан 31 October 2019 в 13:25

Кодирование Значения ключа просто получает доступ к свойству объекта через строку вместо литерального синтаксиса.

// Here is a new instance of an object
Foo *foo = [[Foo alloc] init];
// Accessing a property called someValue with literal syntax:
[foo someValue];
// Accessing the same property with dot notation
foo.someValue;
// Accessing the same property with Key-Value coding:
[foo valueForKey:@"someValue"];

питание KVC состоит в том, что можно указать любую произвольную строку во времени выполнения (очевидно, это могло быть очень опасно также).

28
ответ дан 31 October 2019 в 13:25

Запускаются здесь.

кодирование Значения ключа является механизмом для доступа object’s свойства косвенно, использование строк для идентификации свойств, а не посредством вызова метода доступа или доступа к ним непосредственно через переменные экземпляра.

8
ответ дан 31 October 2019 в 13:25

Другие вопросы по тегам:

Похожие вопросы: