In a previous post I wrote about downloading an image asynchronously. As my work has progressed with my app (which is soon to be released on app store) I realized that the InternetImage class worked very well in the simulator but crashed my application very often on the actual device. The problem with the first version of the class was that it ran by itself, downloading the image and then calling back to it’s delegate when done. The delegate receiver was supposed to release the InternetImage class when it got the message. At first I was very content with the solution and found it pretty neat. However, when images are not downloaded as fast as they are on the simulator with a 24mbit internet connection, there’s a pretty big chance that the user didn’t wait for the image to load before moving to the next view in the application. What happens is:
- An UIView allocs an InternetImage and tells it to start download an image with itself as the delegate receiver.
- The user navigates to the next UIView which deallocs the current UIView.
- A while later the image is downloaded and the InternetImage wants to use it’s delegate to inform the UIView that the image that it’s ready. However, the UIView doesn’t exits and the delegate could now point to whatever.
- The application crashes with “BAD_ACCESS”. Or, the address of the delegate is now pointing to a different object that has been allocated at the same memory address which doesn’t crash the application but we have a memory leak as the InternetImage class doesn’t get dellocated.
This happens more often in a scroll view when you often want to load the next page in advance. On top of this major flaw in the design, it’s not very efficient to download an image that isn’t really needed anymore as the user has already navigate away from the view where it was to be shown.
So now I bring you a much better InternetImage class which is thoroughly tested not only on the simulator but also on a the actual device, my beautiful iPhone 3G .
This is what has been done to fix the flaws:
- When using an InternetImage, make it a member of your class/view by retaining it.
- To prevent the unnecessary download of an image that is no longer needed I’ve added an abort method.
- When deallocating your view/class, always call abort on the InternetImage, then release it.
Other than that the InternetImage class remains the same. I’ve attached the new InternetImage class in a simple sample project. Happy coding!
Download: InternetImage sample