It is great that in Cocoa Touch you can embed a UIWebView in your app and show web content. It’s basically the same view which safari uses to render web pages, so you get years of web rendering development for free.
If you want to use UIWebView the first thing to do is have a look at UIWebViewDelegate protocol:
Quite straightforward to use : you set your viewcontroller (or any other object) to be the delegate for the UIWebView and you can optionally implement
- webViewDidStartLoad – an HTTP request has been started – great place/time to show an activity indicator
- webViewDidFinishLoad – a page has been loaded (including all resources like images, etc) – that’s a great moment to hide your activity indicator
- didFailLoadWithError – error handling
Threading and EXC_BAD_ACCESS
As you can imagine there are several layers of workers in a component as complicated as a web browser – even if you don’t see everything happening behind the curtain – it’s all there, html needs to be parsed, images need to be loaded, css to be applied, etc. etc.
Apple lets you set your UIWebView delegate and be notified when all the work has been done, but if you have some UIWebView controllers inside a navigation controller 0r just more complicated UI you can bump into some sporadic EXC_BAD_ACCESS errors.
The delegate property of UIWebView is non- owning, i.e. it has the assign accessor, thus when the working thread is finished to load all html, css, images, etc. is sends the webViewDidFinishLoad message to the whatever it finds in the delegate property, but it has no way to tell whether the delegate hasn’t been released yet. There you go, if your delegate has been already released (for example you went away from the screen where the web page was supposed to be displayed) – you get a message sent to a released object.
The solution is to set UIWebView’s delegate to nil. The webViewDidFinishLoad message is still sent to it, but since you can send messages to nil it’s actually no problem.
For example in your ViewController class :