So I had a project that supported iOS 4, so all my IBOutlets were __unsafe_unretained
even IBOutlets that were in the nib but outside the controllers main view
For future searchers who come across this question, I think CRD's Stackoverflow answer to a similar question may explain. Even though the object has been deallocated, the memory that's referenced by the unsafe unretained pointer (which contains the actual object data) is not necessarily zeroed, so things may appear to behave properly until that memory is actually reused/modified/zeroed.
I thought that unsafe__unretained was the same as weak but without the zeroing.
It is, yes.
When Cocoa loads the nib, it creates all the objects autoreleased, so they are still there when viewDidLoad
is invoked. However, the autorelease pool has a lifetime that ends when control returns to the run loop. At this point all the objects that aren't owned by anything will go away so any weak outlets will be zeroed at that point.
For most outlets, this is not a problem because objects in the NIB are already generally owned by something anyway. So, for instance, a button in a view is owned by its parent view. Having strong outlets that point to that button are therefore overkill or worse might result in a retain cycle.
Top level objects obviously don't have a parent view to own them so they need to be owned by something else e.g. a controller or "File's Owner". If you are finding stuff disappears, you need to create a strong IBOutlet for it in File's owner.
For more detail, see Apple's docs.
You are correct, the app will crash when trying to access deallocated objects through your stale __unsafe_unretained references.
The reason it doesn't is very likely because the objects are being referenced by some other part of your app with strong references.
Try running with zombies enabled, that should cause an immediate crash when dereferencing the presumedly stale pointers.