Подтвердить что ты не робот

Когда использовать NSNotificationCenter

Я хочу иметь несколько наблюдателей в нескольких событиях одного объекта (отношения 1-к-N).

Механизм для достижения этой задачи обеспечивается NSNotificationCenter. Механизм выглядит довольно переполняющим при использовании для моей проблемы.

Как я сделал бы это вручную без использования NSNotificationCenter:

- (void)addDelegate:(id<DelegateProtocol>)delegate;
- (void)removeDelegate:(id<DelegateProtocol>)delegate;

добавить и удалить наблюдателей из моего объекта.

- (void)someEventFired:(NSObject<NSCopying> *)eventData
{
    for (id delegate in delegates) {
        NSObject *data = [eventData copy];
        [delegate someEventFired:data];
    }
}

Этот механизм является простым и простым в реализации без того, чтобы объекты могли совместно использовать дополнительные строки.

  • Есть ли официальный шаблон для делегатов с 1 по N (например, события С#) в iOS, помимо NSNotificationCenter?
  • Когда следует использовать NSNotificationCenter, а когда нет?
  • Когда должна использоваться реализация, такая как тот, который я предлагаю здесь, а когда нет?
4b9b3361

Ответ 1

По соглашению, делегаты должны, вероятно, использоваться только для отношений 1:1. Если вам действительно нужны отношения 1: N для этого типа функций, у вас есть два варианта:

KVO является подходящим, если вы только заботитесь о том, когда изменяется конкретное свойство объекта. В противном случае вы должны просто рассмотреть возможность использования NSNotificationCenter. Вы даже можете получать уведомления только в том случае, если конкретный объект отправляет это уведомление, передавая этот объект методу addObserver:selector:name:object:.

Apple использует NSNotification в подобных сценариях (например, уведомления, определенные для UITextField, включая UITextFieldTextDidBeginEditingNotification, UITextFieldTextDidChangeNotification и UITextFieldTextDidEndEditingNotification).

Ответ 2

с использованием уведомлений передается: 1 отправитель просто отправляет информацию и кто когда-либо настраивался, получает ее. Мелкая, как радиостанция, нет канала назад (позволяет на мгновение забыть о телефонах)

Делегация - это нечто другое. Th-объект, который запрашивает у deleagte что-то делать, обычно нуждается в результате этого запроса, поэтому делегирование - это сообщение 1 к 1, которое всегда инициируется объектом, а не делегатом (в то время как объект может иметь методы, которые может быть вызван для информирования объекта об инициировании связи, то есть [tableView reloadData]).

Итак, если отправителю необходимо вернуть данные, это делегирование. Если отправителю ничего не нужно после трансляции, отправляйте уведомления.

Если вы столкнулись с ситуацией, вам нужна делегирование, но несколько объектов должны реализовать протокол. у вас должно быть 1 делегат, который содержит ссылки на другие объекты и вызывает методы от имени отправителей - или вы можете пойти с блоками.

Ответ 3

NSNotificationCenter не является излишним для того, что вы предлагаете, это точно правильное решение. Это мешает наблюдаемому объекту знать или заботиться о своих наблюдателях, делая ваш код более слабо связанным и чистым.

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

Ответ 4

Ваше предлагаемое решение не проще, чем использование NSNotificationCenter, и оно не является потокобезопасным.

Чтобы сделать поток решений безопасным, вам необходимо предоставить механизм для предотвращения изменения массива делегатов во время работы диспетчера событий для цикла.

Ваше решение также требует, чтобы вы поддерживали массив делегатов в своем классе. С NotificationCenter вы можете просто использовать центр по умолчанию, и вам не нужно реализовывать методы добавления/удаления в вашем классе. Вместо этого экземпляры могут регистрироваться для получения уведомлений, поскольку они лучше всего подходят (селектор/блок, очередь, источник). Ваш исходный класс не должен беспокоиться об этих деталях. Ему нужно только зарегистрироваться в качестве источника уведомлений определенного типа. Использование блоков для обработки уведомлений действительно удобно.

Альтернативой центру уведомлений является использование Key-Value-Observing, если это соответствует потребностям вашего прецедента.

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

Ответ 5

Отношения между делегатами от 1 до N не имеют смысла. Посмотрите

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row

например. Что делать, если у этого объекта действительно было n делегатов? Как он должен решить, какие из n представлений, которые он получает от всех своих делегатов, следует использовать? Делегаты - это именно этот принцип 1-к-1.

Центр NSNotificationCenter - это правильный подход. Просто используйте

addObserver:selector:name:object:

соответственно

postNotification:

Это определенно не слишком много кода. И это очень легко для вас, поскольку центр обрабатывает все вызовы.

Ответ 6

Вы не хотите использовать NSNotificationCenter для чего-либо, кроме общесистемных событий (например, появления клавиатуры или какого-либо подобного события). Причина в том, что он полностью не безопасен для типов, может сделать все зависимым от всего и что вы больше не получаете проверки времени компиляции или результаты поиска.

KVO, на мой взгляд, не должен использоваться для наблюдения за изменениями за пределами объекта, который вы слушаете, поскольку он имеет похожие вниз стороны (нет проверки времени компиляции, сбои, если вы не удаляете слушателей должным образом или не регистрируете их дважды).

Образец addDelegate/removeDelegate, который вы представляете, является, по-моему, правильным правилом, поскольку имеет преимущество в том, что он поддерживает проверку безопасности типов и компилятора и делает явно явные зависимости. Единственная проблема заключается в том, что Apple не предоставляет готовое решение для этого шаблона, так как вам нужен тип коллекции, который слабо сохраняет свои элементы, чтобы избежать сохранения циклов.

Однако, см. код из моего BMCommons framework, который решает эту проблему аккуратно, используя BMNullableArray и макросы. См. BMCore.h заголовок для определения этих макросов:

BM_LISTENER_METHOD_DECLARATION(protocol)
BM_LISTENER_METHOD_IMPLEMENTATION(protocol)

Реализация гарантирует, что один и тот же слушатель никогда не будет добавлен дважды, а также то, что слушатели слабо сохраняются, не вызывая какого-либо сбоя, даже если они забывают отменить регистрацию при освобождении (хотя я предпочитаю ловить это условие с помощью assert, поскольку это ошибка программирования).

Ответ 7

Я говорю, что NSNotificationCenter должен ВСЕГДА использоваться над моделью делегата, за исключением ситуаций, когда вы запрашиваете делегат по информации (например, -webView:shouldLoadRequest:). Он более стабилен, проще в реализации и приводит к более чистым кодам, а затем пытается использовать делегат. Другая альтернатива - это блоки, которые могут быть хорошими, но они могут быть больно, когда дело доходит до управления памятью.

В конце концов, это зависит от вас, но я думаю, что NSNotificationCenter - это лучший способ работать практически в любой ситуации, если только для нескольких функций наблюдателя.