I have an application that uses UIWebViews
in several view controllers. The UIWebViews
are used to render locally generated html, no slow network access required.
To save memory I only load these on demand as prompted by the viewcontroller viewWillAppear
callback. (And unload offscreen instances in response to didReceiveMemoryWarning
messages.)
The problem is that the user gets to see the html being rendered, sometimes accompanied by flashes of styling and other assorted unpleasant artifacts. I would much rather the rendering be done offscreen, and reveal the fully rendered view when its ready.
It would be very tidy to be able to have the viewWillAppear
not return until the UIWebView is fully rendered. But how?
I tell the UIWebView
what to render by sending it a loadHTMLString:baseURL:
message. This is asynchronous, and some time (soon) later the webview's delegate gets called back webViewDidFinishLoad
.
I experimented with running a runloop inside viewWillAppear
, running either the NSDefaultRunLoopMode
or UITrackingRunLoopMode
. This works in the simulator (it complains to the log
[CATransaction synchronize] called within transaction
but does work) but on a device it deadlocks, with webViewDidFinishLoad
never being called.
(Also, it seems like the UIWebView
loading property doesn't work. At least, after I call loadHTMLString:baseURL:
and before getting the callback it's not true.)
The method viewWillAppear: is triggered in response to a change in the state of the application, indicating that the view controller is becoming “active.” The reason viewDidLoad exists – the only reason – is that it sometimes isn’t possible or efficient to configure 100% of an interface in a XIB.
Sometimes, you use auto layout, and you realize that the editor for that is actually worse than writing auto layout code. Thus, viewDidLoad is sent to a view controller right after its XIB file is loaded to allow you to perform this additional customization of views.
UIView Controller. View Will Appear (Boolean) Method Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here. Called prior to the View being added to the view hierarchy.
The second method to defer parsing of JavaScript is to use Cloudflare Rocket Loader that prioritizes your actual website’s content (text, images etc) by deferring the loading of the JS. Your JS will be parsed after rendering your web page, not before. Rocket Loader can be enabled directly from your Cloudflare Dashboard:
Lots of solutions here I think. A quick one is to load your UIWebView with it's hidden property set to YES. Then set your UIViewController as the UIWebViews delegate and implement:
- (void)webViewDidFinishLoad:(UIWebView *)webView
where you set the property back to NO.
A thing to note is that webViewDidFinishLoad will fire more than once if you have framed/embedded content. So you have to keep track of this. Shouldn't really be a problem if you are loading local content.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With