I've been working on my latest project since April. That is a long time, but life gets in the way. Regardless, this period of time means that my app has had to make the transition to iOS 4.2. If you'll recall my post about caching media, my app loads a fair amount of media from the web and displays it all to the user. On iOS 3.2, the images I was loading would gradually show up on the screen one by one. Once I upgraded my iPad to 4.2, this functionality suddenly changed: the images would load all together at once. This is bad because it takes a long time to display, decode, and render these images. The user would have to wait many seconds before they were seen. Since my app is so visual, this was unacceptable, so I started debugging.
My first inclination was that something might have changed about how the resources were being downloaded due to differences in the way NSOperation was being handled. I placed a bunch of debug output to find out that images were downloading the same way as before, so the problem was happening after I set the image property of the target UIImageView. I wrestled with what could be happening for a while until I realized that I was setting the property on a thread other than the UI thread. I was also setting it within an @synchronized block. So, I thought the lock might be causing the problem. However, I found the entire locked area was taking 4ms of time. When you have synchronous debug prints coming over a channel, this is a small amount of time. So, Apple had changed the way image rendering was happening to queue things up to run in some batched run loop mode on the UI thread. I ran with this and changed the rendering operation to flip the render over to the main thread with performSelectorOnMainThread. It worked! I was lucky that this solved the problem as it was only a hunch. While I had played around with performSelectorOnMainThread before, I found memory management with it is tricky and so I had stayed away from it. I'm sure there are some reference counting issues in the code now as a result of the change. Lesson learned: on iOS, perform UI changes on the main thread only. The pain of retainCount management is worth it.~siOS: UIImageView rendering in 4.2