KVO различие между willChangeValueForKey и didChangeValueForKey - оба необходимы? - PullRequest
5 голосов
/ 06 декабря 2011

В соответствии с собственными рекомендациями Apple, при настройке аксессоров, совместимых с KVC / KVO, следует включать ОБА Методы KVO willChange и didChange. Это то, что я сделал во всех моих ручных методах доступа.

Однако observeValueForKeyPath:ofObject:change:context вызывается для каждой половины методов KVC (будет и сделал) с точно одинаковым содержимым словаря.

При регистрации наблюдателя с помощью опции: NSKeyValueObservingOptionPrior наблюдатель по-прежнему вызывается дважды - по одному разу для каждой половины - и, опять же, с одинаково одинаковым содержанием словаря, сохраните только ту разницу, которую ключ «NotificationIsPrior» включен в словарь.

Теперь, когда KVO используется для изменения атрибутов «дорогой ЦП» - таких как изменение цвета или перерисовка большого и сложного дизайна, имеет смысл только воздействовать на «didChange» и игнорировать (или, по крайней мере, выделять) «Воля». Раньше я добивался этого путем преобразования строки ключа в элемент списка enum, который возвращает сдвинутую влево цифру «1», и использовал эту цифру для установки флага в 32- или 64-битном целом числе при получении первого вызова и когда флаг сбрасывается на второй, я выполняю операции с интенсивным использованием процессора.

Однако меня поражает, что это нетривиальные накладные расходы для реализации в каждом случае. Есть ли у кого-нибудь другой «предпочтительный» способ разграничения между обратным вызовом для willChange и обратным вызовом для didChange, не позволяя выполнить одну и ту же обработку дважды?

Я изучил собственную документацию Apple и эту группу помощи обильно для альтернативных вариантов, но собственный документ Apple на самом деле не вдавался в подробности по этому вопросу, и несколько человек в этой группе также боролись с похожей проблемой. Ни в одном случае не было предложено окончательное решение. Если кто-нибудь знает лучший способ - кроме уклонения от 'willChange' с использованием чередующихся флагов - я был бы очень благодарен. (Почему Apple не может просто включить ключ фазы в словарь изменений ???)

1 Ответ

5 голосов
/ 15 декабря 2011

Я думаю, что это то, что вы получили в комментариях, но для будущих посетителей:

Если вы хотите сказать, является ли обратный вызов «до» или «после», вы можете искатьключ NSKeyValueChangeNotificationIsPriorKey в словаре изменений.Если это предварительное уведомление, этот ключ будет равен [NSNumber numberWithBool: YES] (кстати, словарь также не будет содержать значение для NSKeyValueChangeNewKey) Наличие / значение NSKeyValueChangeNotificationIsPriorKey является достоверным, поэтому, если вы видите его, когда это не такожидая, что вы можете получить двойные обратные вызовы.

Если вы получаете двойные обратные вызовы, может случиться так, как это было в случае VectorVictors, что среда выполнения запускает их И вы запускаете их.Если вы планируете вызывать will / didChangeValueForKey: для управления своими уведомлениями KVO вручную (и вам не нужны двойные уведомления), вам следует реализовать следующий метод класса:

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {

    BOOL automatic = NO;
    if ([theKey isEqualToString:@"propertyYourePlanningToManageYourself"]) {
        automatic = NO;
    } else {
        automatic=[super automaticallyNotifiesObserversForKey:theKey];
    }
    return automatic;
}

Это подробно описано вApple Руководство по программированию наблюдения значения ключа.

...