Building an info screen for your iOS app using UIWebView

November 9, 2011 by · Leave a Comment
Filed under: iOS 

For my upcoming iPhone app I was looking for an easy way to add an info screen that describes the app and some of the features. I found a lot of mentions of “use UIWebView”, but I couldn’t find a comprehensive tutorial or list of steps. So here is a description of the implementation I came up with and some issues that I ran into.

Building the View

The view is relatively simple – all it has is an instance of UIWebView. Here is the header file:

#import <UIKit/UIKit.h>

@interface InfoViewController : UIViewController <UIWebViewDelegate> {
    UIWebView *webView;
}
@property (nonatomic, retain) UIWebView *webView;

@end

In the init-method, the UIWebView is instantiated and made to use the whole area:

- (id) init {
    [super init];
    if (self) {
        //set title to navItem
        [[self navigationItem] setTitle:@"Info"];

        // add webView
        CGRect bounds = [self.view bounds];
        bounds.size.height = bounds.size.height - 48; //height for navItem        
        webView = [[UIWebView alloc] initWithFrame: bounds];
        webView.delegate = self;
        
        [[self view] addSubview:webView];
    }
    return self;
}

I’m not really happy with the “magical“ 48 pixels to account for the navItem, but at least it’s working fine. (If you have a better way, please let me know!)

Displaying Info Text

Displaying HTML

Once the view is initialized, displaying an HTML-page such as help.html is pretty simple:

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    //build a request to display help.html
    [webView loadRequest:[NSURLRequest requestWithURL:
            [NSURL fileURLWithPath:[
                [NSBundle mainBundle] pathForResource:@"help" ofType:@"html"]
                    isDirectory:NO]]];
}

You just have to add the file help.html to your project and make sure it is part of the target. It gets copied to the simulator or iPhone as part of the installation procedure. You can also include some CSS to properly style the html document (especially for aspects such as fonts or padding).

Displaying local images

In order to display images in the html, you just have to reference like this in the html-file:

<img src="ScreenshotTop.png" alt="Screenshot Top Part" width="288" height="214"/>

If you google for “UIWebView local image”, there are a lot of references to setting the baseURL of the UIWebView. I couldn’t get this to work properly, but instead found that simple references to png-files just work (whereas jpg-files did not work).

As with all images, they should be properly scaled to the dimensions that you want them to be displayed in order to avoid any re-sizing on the device which can take quite some time for screenshots.

Displaying the view

Adding an Info Button to the Navigation Bar

There is a standard info button (UIButtonTypeInfoLight) that is ideal for an info screen, but it can’t be used directly in a navigation bar. I order to use this standard button, you have to wrap this button in an UIBarButtomItem:

UIButton* infoButton = [UIButton buttonWithType: UIButtonTypeInfoLight];
[infoButton addTarget:self action:@selector(showInfo) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *infoBarButton = [[UIBarButtonItem alloc] initWithCustomView:infoButton];
[self.navigationItem setRightBarButtonItem: infoBarButton animated:YES];
[infoBarButton release];
[infoButton release];

Showing the info view

In order to show the view, you just initialize the InfoViewController and push it on the display stack:

-(void) showInfo {
    if (!infoViewController) {
        infoViewController = [[InfoViewController alloc] init];
    }
    [[self navigationController] pushViewController:infoViewController animated:YES];    
}

Handling Links

When you include links in your html-file (such as to your website, to your product FAQ on the web or a mailto: your support email address), you want them to open in the corresponding app (and not in your UIWebView). In order to do that, you have to implement the UIWebViewDelegate protocol in your InfoViewController, especially the following method:

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; 
{
    if ((navigationType == UIWebViewNavigationTypeLinkClicked) || ([request.URL.scheme isEqualToString:@"mailto"])) {
        [[UIApplication sharedApplication] openURL:request.URL];
        return false; //will open links in Safari or MailApp
    } else {
        return true;
    }
} 

This method is called whenever a request starts to be loaded in the UIWebView. It looks if is called because a link was clicked (NavigationTypeLinkClicked) or the URL scheme is “mailto”. If that’s the case then we open that link in the “sharedApplication” which is Safari (for web pages) or the MailApp (for mailto’s).