is it ok to use of a notification to communication back to the main thread of an IOS app? (cf performSelectorOnMainThread)
Asked Answered
Z

2

13

Is it ok to use of a notification to communication back to the main thread of an IOS app? (cf performSelectorOnMainThread). That is, there are are there any gottcha's for this purpose?

Background

  • want to call back to main UI thread from a background thread (e.g. performSelectorInBackground)
  • could use performSelectorOnMainThread to communicate back, but wondering if it is OK to use a notification?

For example

 [[NSNotificationCenter defaultCenter] postNotificationName:@"ModelChanged" object:self];
Zebrawood answered 7/11, 2011 at 4:13 Comment(0)
A
20

Actually there is a gottcha; you'll crash randomly! That has been my experience. This has to do with the fact that the object receiving the notification does so on the same thread as the notification's sender.

From the Apple iOS Documentation on Notification Centers:

In a multithreaded application, notifications are always delivered in the thread in which the notification was posted, which may not be the same thread in which an observer registered itself.

This will inevitably cause you headaches.

If the notification is being received by something on the main thread, I've found that popping into the main thread from the background thread to issue a notification is the safest way to go about this. It is quite simple to do:

//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];
}

Unfortunately this introduces a subtle coupling between the sender and receiver in that you are modifying the sender to accommodate the receiver.

An even better solution, as XJones points out, is to have the sender send out the notification on whatever thread it decides to, and then to make the listener responsible for using the proper thread to perform whatever action it needs to.

Hope that was helpful.

Acidimetry answered 7/11, 2011 at 6:25 Comment(5)
I referenced this problem in a comment in my answer. I don't like your solution exactly b/c of the coupling between the object posting the notification and the observer. The object posting should post on whatever thread it likes. The receiver should handle the notification on the thread it needs to (e.g. the receiver can forward the notification to the main thread or any other thread). Apple uses this method in its sample code as well.Swiss
I completely agree. I've updated my answer to reflect this method.Acidimetry
@Acidimetry I understand the coupling in this method, but how would I go about making the receiver listen on multiple threads?Snatchy
@AlexGodbehere The listener is not able to dictate which thread it receives a message on. Your best strategy is to receive the message on whatever thread it comes in on (because you don't have a choice unless you want to control the sender), and then from the receiver, perform whatever action you wanted to on whatever thread you wish to use. Hope that answered your question.Acidimetry
[[NSOperationQueue mainQueue] addOperationWithBlock:^ {}]; Usually is a cleaner alter for performSelectorOnMainThread:Playhouse
S
8

Yep, notifications can be used for this purpose. you can use any method you like (protocols, notifications, direct messaging) to communicate between objects across threads. Which one you choose depends on what you feel is most appropriate. Notifications are great when the object posting the notification doesn't know anything about the objects observing the notification. If you send a message (e.g. performSelectorOnMainThread) then the object sending the message does need to know about the object it is sending the message to (typically through a protocol).

Swiss answered 7/11, 2011 at 5:19 Comment(2)
ok thanks - I've had some problems (#8033487) and wondering if this might have been the reasonZebrawood
ok, just posted an answer on that one. I generally find it better to enforce any thread requirements in handlers vs at the sender. For example, you can make sure you always post notifications on the main thread but this is tedious. The posting object shouldn't care. The recipient does care and should forward the message to the main thread if appropriate.Swiss

© 2022 - 2024 — McMap. All rights reserved.