It's not just the notification center.
I have a class containing a method with a loop. I need to be able to break the loop if a certain event (e.g. button press) occurs.
The events for that button press come in on the main thread. If your loop is running on the main thread, then the button press itself does not get processed until your loop is finished. The notification is posted immediately, relative to the button press actually getting processed by your application.
Or, in list form:
- The user presses the button.
- Your loop runs out of things to do and returns.
- The button press arrives in your application and is turned by the button into an action message.
- You post the notification.
- You receive the notification.
The delay that you're seeing is between steps 1 and 2; step 4 happens immediately after step 3.
Notifications on a local (not distributed) NSNotificationCenter are dispatched on the thread you post them from, so posting it from your action method means that it will be dispatched on the main thread. This is normal and OK.
Move the loop, not the notification, to a background thread, dispatch queue, or operation queue. If you use an operation queue, you may not need the notification at all, as you can tell an operation queue to cancel all pending operations. (Your operations will need to check at any appropriate time(s) whether they have been canceled; for reasons previously discussed, killing a thread/operation at a random time is a Bad Idea.)
Background threads, blocks, and operations can communicate back to the main thread when needed (e.g., to update the UI). To send a message through the main thread's run loop, use performSelectorOnMainThread:withObject:waitUntilDone:
. To dispatch a block on the main thread, use dispatch_async
and dispatch_get_main_queue
. To schedule an operation on the main thread, add it to [NSOperationQueue mainQueue]
.
For more info, read the Concurrency Programming Guide and the Notification Programming Topics.