Please, please, please do not try to use NSExceptions
for view invalidation. I'm not even sure how that would work, but please don't try. Unlike in other frameworks/languages (like Java or .NET), in Cocoa, exceptions usually mean "something has gone horribly wrong and the app should terminate." (Yes, there are a handful of exceptions to that rule, but "view invalidation" isn't one of them.)
The first thing to know is that UI (i.e. views) objects are typically regarded as main-thread only. So if you're mutating your model on a background thread, the invalidation of the view should be marshaled to the main thread. GCD has facilities to handle this (dispatch_get_main_queue
) but there are others as well, such as -[NSObject performSelectorOnMainThread:...]
and CFRunLoopPerformBlock
.
The next thing to know is that if you're going to do this (i.e. read your model on the main thread to populate the UI, and update your model from background threads) you will need to have some sort of locking system to be sure that no background threads are mutating the model while the main thread is trying to read from it. You can marshal invalidation to the main thread without a lock, but when the views go to re-validate (i.e. layout and draw) you will want to take an appropriate lock for the model objects being represented to prevent data corruption. Managing these locks can rapidly get non-trivial. (Although private concurrent GCD queues accessed with dispatch_(a)sync
& dispatch_barrier_(a)sync
are a pretty good place to start.)
One common pattern that avoids most of the locking complexity is to have background threads do their work on a copy of the model and then send not only the view invalidation, but also the model mutation operation back to the main thread, so in terms of the "one, true model", it is always main thread only, in which case you don't need to worry about locking. If you can do things this way, it will save you a LOT of grief.
On OSX (but not iOS) there are Cocoa bindings, which use Key-Value Observing (with a bunch of other opaque "magic" in between) to automatically invalidate and update bound UI when the model changes. Cocoa bindings don't exist on iOS, but it's worth mentioning in that KVO does and the notifications it sends could be used for view invalidation. The important thing to know with that is that KVO notifications are sent synchronously on the thread that the mutation takes place on, so again, you would want to marshal your mutations back to the main thread.
Lastly, using NSNotificationCenter doesn't free you from worrying about locking and cross-thread notifications either because, like KVO, NSNotifications are delivered synchronously on the thread on which they're posted. Sending an NSNotification on a background thread for which there are UIViews observers is going to cause problems too.