Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIWebView delay in loading local content

I'm displayed a small amount of local content in a UIWebView, roughly 3 paragraphs of text and one 100x100px image. When the UIWebView is pushed onto to the nav controller, it takes about half a second before the content is displayed. This occurs on the device, not in the simulator. Obviously the UIWebView needs to do some work before displaying the content, but is there some way I can do this before the pushed view appears? I have not had any luck doing this myself.

Here is where I'm creating and pushing the view controller which contains the UIWebView:

ArticleViewController* viewController = [[ArticleViewController alloc] init];
viewController.article = article;
[viewController view]; //touch the view so it gets loaded
[viewController loadWebView]; //load the web view content
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];

And here is the loadWebView method:

-(void)loadWebView {
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSURL *baseURL = [NSURL fileURLWithPath:path];

    NSString* content = article.content;

    NSString *html = [NSString stringWithFormat:@"\
                      <html><body style='background-color: transparent'><style type=""text/css"">body {font-family: helvetica; color: black; font-size: 10pt; margin: 10px 10px 10px 10px}</style>\
                      %@<div style='text-align:center'><a href='13443574_9709e4cf37.jpg?photographer=test' style='-webkit-tap-highlight-color:rgba(0,0,0,0);'><img src='13443574_9709e4cf37.jpg' height='160' width='230'></a></div></body></html>", content];
    [self.webView loadHTMLString:html baseURL:baseURL];
}

Previously I had [viewController loadWebView] in the viewDidLoad method, but the result seems to be the same. A blank screen when the viewController is pushed, followed by the content loading half a second later.

Any ideas?

like image 442
Ben Williams Avatar asked Oct 04 '10 01:10

Ben Williams


2 Answers

Problem Confirmed

I too see a half-second or more delay with a white screen before my UIWebView content appears. This happens only on the first use of a UIWebView during that run of the app. Successive appearances of UIWebView are nearly instantaneous. So it seems to me and other folk that the delay must be due to WebKit libraries needing to load and initialize.

Warm-up WebKit

You cannot eliminate the delay. But you can move that delay to the start of your app, to lessen the annoying effect of "blank screen" to your users. The trick is to load UIWebView with a bogus page off-screen, during your app's launch. Build a minimal HTML5 web page in a hard-coded string. I use a correct and valid HTML5 content to minimize the time taken by UIWebView/WebKit to analyze.

This technique works noticeably well on real hardware (iPhone 3GS), not just the iOS Simulator.

In my app delegates didFinishLaunchingWithOptions method, the bottom of the ARC-compliant code looks like this:

…
[self.window makeKeyAndVisible];

// Performance optimization: Warm up the UIWebView widget and its related WebKit libraries.
// We are choosing the trade-off between (A) a slight delay here during app launch to create and abandon a bogus UIWebView instance, and
// (B) a flash of white and noticeable delay as the UINavigationController slides in from the right the first UIWebView we display during the app run.
UIWebView* bogusWebView = [[UIWebView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
NSString* html = @"<!doctype html><html lang=en><head><meta charset=utf-8><title>blah</title></head><body><p>bogus content</p></body></html>";
[bogusWebView loadHTMLString:html baseURL:nil]; // Load the page.
bogusWebView = nil; // Not really needed, but self-documents that we intend to discard this object.

return YES;

This technique seems to reduce most but not quite all of the approximate half-second delay during the user's first appearance of UIWebView on screen. I conclude that most of the delay is due to WebKit warming up, but there must be some overhead related to graphically presenting a UIWebView on-screen. If so, we cannot eliminate that remaining overhead with off-screen work. But nevertheless, this technique eliminates most of the initial delay. So the user's first impression of my app won't be "slow".

like image 88
Basil Bourque Avatar answered Oct 24 '22 06:10

Basil Bourque


You're going to make the user wait, the only question is: is it before or after the webview appears? If you're set on "before", then you should create the controller, load the web view, but wait to push it until the -webViewDidFinishLoad: delegate method fires. Once you receive that, you can push the view.

like image 28
Ben Gottlieb Avatar answered Oct 24 '22 06:10

Ben Gottlieb