Какой самый лучший способ сделать наблюдатель/наблюдаемый в objective-c (версия для iphone)
Я использую кодирование пользовательских интерфейсов Java Swing, а в тех случаях, когда у вас есть некоторые свойства, которые изменяются, и вы хотите обновить свой интерфейс, вы должны реализовать наблюдаемый/наблюдаемый шаблон. В Java вы обычно это делаете, если ваш класс поддерживает список слушателей, что он уведомляет о различных событиях.
Я играл с Objective-C на Mac, и у него есть KVC и привязка, которая, кажется, работает очень красиво и требует меньше кода. IPhone SDK, похоже, не обладает этой функциональностью, поэтому мой вопрос:
Если у меня есть класс, который содержит данные, которые меняются, что лучший способ для меня зарегистрировать компонент пользовательского интерфейса с этим классом, чтобы он мог быть уведомлен об изменениях в данных, которые он должен отображать?
Ответы
Ответ 1
Существует два встроенных способа наблюдения в Cocoa: наблюдение за ключами и уведомления. Ни в одной из систем вам не нужно самостоятельно поддерживать или уведомлять коллекцию наблюдателей; структура будет обрабатывать это для вас.
Наблюдение за ключевыми значениями (KVO) позволяет вам наблюдать свойство объекта, включая даже свойство, представляющее коллекцию, и получать уведомления об изменениях в этом свойстве. Вам просто нужно отправить объект -addObserver:forKeyPath:options:context:
, передающий объект, который хотите получать обновления, путь к ключу свойства (относительно получателя), для которого вы хотите получать обновления, и типы обновлений, которые вы хотите получить. (Существуют аналогичные методы, которые вы можете использовать, если хотите наблюдать свойство, представляющее коллекцию.)
Уведомления старше и тяжелее. Вы регистрируетесь с помощью NSNotificationCenter
- обычно центра по умолчанию - пары объектов и селекторов, которым передается уведомление при возникновении события. Сам объект уведомления может содержать произвольные данные через его свойство userInfo
, и вы можете наблюдать за всеми уведомлениями определенного имени, а не с теми, которые относятся к определенному объекту.
Что вы должны использовать в любом конкретном случае? В общем случае, если вы заботитесь об изменениях в конкретном свойстве конкретного объекта, используйте наблюдение за ключевыми значениями. То, для чего оно предназначено, и намеренно легкое. (Среди других применений это основа, на которой построены привязки Cocoa.) Если вы заботитесь об изменении состояния, которое не представлено свойством, тогда уведомления более уместны.
Например, чтобы оставаться в синхронизации, когда пользователь меняет имя объекта модели, я бы использовал KVO. Чтобы узнать, когда был сохранен весь граф объектов, я бы использовал уведомления.
Ответ 2
Я также обнаружил, что вы можете сделать:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleWhateverChange) name:@"whateverChange" object:nil];
Чтобы зарегистрироваться для событий изменений и
[[NSNotificationCenter defaultCenter] postNotificationName:@"whateverChange" object:nil];
Чтобы уволить их. Я мог бы быть N00b, но я просто не мог заставить наблюдателя использовать ключевой путь для меня.
Ответ 3
Это не так, как это было сделано. Взгляните на обсуждение here, в частности ссылку на документацию Apple.
Если вы все еще хотите сделать это так, как вы говорите, это не особенно сложно реализовать что-то вроде привязки "вручную". Вы просто создали объект привязки, который знает, как подписаться на изменения, и подключается к свойству представления.
Чтобы на самом деле ответить, как это сделать - обычно у вас есть объект контроллера, который контролирует состояние модели (действуя что-то вроде Observer) и обновляет объект просмотра по мере необходимости.