Нормально ли использовать уведомление для связи обратно в основной поток приложения IOS? (cf выполнитьSelectorOnMainThread)

Можно ли использовать уведомление для связи обратно в основной поток приложения IOS? (cf выполнитьSelectorOnMainThread). То есть, есть ли какие-либо gottcha для этой цели?

Фон

  • хотите перезвонить в основной поток пользовательского интерфейса из фонового потока (например, выполнитьSelectorInBackground)
  • может использовать функцию performSelectorOnMainThread для обратной связи, но интересно, можно ли использовать уведомление?

Например

 [[NSNotificationCenter defaultCenter] postNotificationName:@"ModelChanged" object:self];

Ответ 1

На самом деле есть gottcha; вы рухнете случайно! Это был мой опыт. Это связано с тем, что объект, получающий уведомление, делает это в том же потоке, что и отправитель уведомлений.

Из Документация Apple iOS в Центрах уведомлений:

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

Это неизбежно вызовет у вас головные боли.

Если уведомление получено чем-то в основном потоке, я обнаружил, что всплывающее сообщение в основном потоке из фонового потока, чтобы выдать уведомление, является самым безопасным способом для этого. Это довольно просто:

//Call this to post a notification and are on a background thread      
- (void) postmyNotification{
  [self performSelectorOnMainThread:@selector(helperMethod:) withObject:Nil waitUntilDone:NO];
}

//Do not call this directly if you are running on a background thread.
- (void) helperMethod{
  [[NSNotificationCenter defaultCenter] postNotificationName:@"SOMENAME" object:self];
}

К сожалению, это вводит тонкую связь между отправителем и получателем в том, что вы изменяете отправителя для размещения приемника.

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

Надеюсь, что это было полезно.

Ответ 2

Да, для этой цели можно использовать уведомления. вы можете использовать любой способ, который вам нравится (протоколы, уведомления, прямой обмен сообщениями) для обмена информацией между объектами по потокам. Какой из них вы выбираете, зависит от того, что вы считаете наиболее подходящим. Уведомления отличные, когда объект, отправляющий уведомление, ничего не знает об объектах, наблюдающих уведомление. Если вы отправляете сообщение (например, performSelectorOnMainThread), то объект, отправляющий сообщение, должен знать об объекте, по которому он отправляет сообщение (обычно через протокол).