I was working on an app last week that had a strange problem, it would without warning lose some of its subviews during the course of using it. With little documentation of why this was happening it was a tricky problem to solve, but I managed to figure it out eventually.
The first clue was they would always disappear after presenting a UIImagePickerController for the camera, this seemed strange as the view controllers were separate, however whenever it presented this view the console would log a memory warning. This was interesting because it at least showed that the app was running low on memory (despite it being only 5mb in the RAM according to the Profiler). After removing all the apps in the memory and then running the app, this problem didn’t present itself. It would nice if that was the end of it, but most people would have plenty of apps running in the background, so this problem would therefore affect most users.
I eventually tracked it down to a problem viewDidLoad, I used a boolean to determine whether to create the new subviews (because why create them twice?), however when viewDidUnload gets called, what the view controller actually does is remove the subviews from the view controller that were created with NIB’s or in viewDidLoad, so when it came time to call viewDidLoad for a second time it wouldn’t execute because the boolean flag was already tripped. It seems stupid that the views should be able to just be thrown out at the whim of the operating system, but it makes sense if you consider that they will get recreated when they are needed (in viewDidLoad), this leaves more memory to play with. The reason this never happened to me before was because I usually created these views in awakeFromNib, which doesn’t come into the view controllers lifecycle scope.
iOS can be a strange OS to develop on at times, but there is a method to the madness that it employs, it’s simply trying to be as efficient as possible.