Display a page of HTML in a UIWebView

A UIWebView is like a browser. This UIWebView displays the page http://i5.nyu.edu/~mm64/INFO1-CE9236/src/html/preview.html. But a UIWebView is a browser with no back button or place to type a URL. If you tap on the links to www.filmratings.com or www.mpaa.org, there will be no way to get back to the green page.

Source code in HTML.zip

  1. main.m
  2. Class HTMLAppDelegate
  3. Class ViewController
  4. HTML-Info.plist: initially landscape, supports only landscape, status bar hidden.
  5. preview.html (not used until the exercise where we call the stringWithContentsOfFile:encoding:error: method of class NSString)

Create the project

The HTML-Info.plist file must have the following keys:

  1. Set UISupportedInterfaceOrientations and UIInterfaceOrientation to UIInterfaceOrientationLandscapeLeft.
  2. Set UIStatusBarHidden to YES.

Three sources from which to get the page of HTML

  1. Download it from the web. The following code in the loadView method of class ViewController downloaded a file of HTML from the web into the UIWebView named webView.
    		NSURL *url = [NSURL URLWithString:
    			@"http://i5.nyu.edu/~mm64/INFO1-CE9236/src/html/preview.html"];
    
    		NSData *data = [NSData dataWithContentsOfURL: url];
    
    		if (data == nil) {
    			NSLog(@"could not load URL %@", url);
    			return;
    		}
    
    		[webView loadData: data
    			MIMEType: @"text/html"
    			textEncodingName: @"NSUTF8StringEncoding"
    			baseURL: url
    		];
    
    
  2. Get the HTML from a file in the app’s bundle. Replace the above code with the following. The file preview.html has already been added to the project. It is a plain text file that can be created with TextEdit.app or the Unix editor vi.
    		NSBundle *bundle = [NSBundle mainBundle];
    
    		NSString *fileName =
    			[bundle pathForResource: @"preview" ofType: @"html"];
    
    		NSError *error = nil;
    		NSString *html = [NSString stringWithContentsOfFile: fileName
    			encoding: NSUTF8StringEncoding
    			error: &error
    		];
    
    		if (html == nil) {
    			NSLog(@"error == %@", error);
    			return nil;
    		}
    
    		[webView loadHTMLString: html baseURL: nil];
    
  3. Hardcode the HTML into the app. Replace the above code with the following.
    		NSString *html =
    			@"<HTML>"
    			"<HEAD>"
    			"<META NAME = \"viewport\" CONTENT = \"width = device-width\">"
    			"<STYLE TYPE = \"text/css\">"
    			"<!--"
    			"SPAN.big  {font-size: 125%; font-weight: bold; padding: .33em;}"
    			"A:link    {font-size:  75%; color: white; text-decoration: none;}"
    			"A:visited {font-size:  75%; color: white; text-decoration: none;}"
    			"-->"
    			"</STYLE>"
    			"</HEAD>"
    
    			"<BODY STYLE = \"background-color: green; margin: 0px;\">"
    
    			"<TABLE STYLE = \""
    			"\tcolor: white;"
    			"\tfont: medium/200% Helvetica, sans serif;"
    			"\tmargin: auto;"
    			"\text-shadow: black .2em .2em 0;"
    			"\">"
    
    			"<TR>"
    			"<TD ALIGN = \"CENTER\" COLSPAN = \"2\""
    			"STYLE = \"padding-top: 7em; padding-bottom: 5em;\">"
    			"THE FOLLOWING"
    			"<SPAN CLASS = \"big\">PREVIEW</SPAN>"
    			"HAS BEEN APPROVED FOR"
    			"<BR><SPAN CLASS = \"big\">ALL AUDIENCES</SPAN>"
    			"<BR>BY THE MOTION PICTURE ASSOCIATION OF AMERICA, INC."
    			"</TD>"
    			"</TR>"
    
    			"<TR>"
    			"<TD ALIGN = \"LEFT\">"
    			"<A HREF = \"http://www.filmratings.com/\">www.filmratings.com</A>"
    			"</TD>"
    			""
    			"<TD ALIGN = \"RIGHT\">"
    			"<A HREF = \"http://www.mpaa.org/\">www.mpaa.org</A>"
    			"</TD>"
    			"</TR>"
    			"</TABLE>"
    			""
    			"</BODY>"
    			"</HTML>";
    
    		[webView loadHTMLString: html baseURL: nil];
    

Things to try

  1. After you have faded the green band in, fade it out. In the loadView method of class ViewController, change the word NULL to the following block.
    	^ (BOOL b) {
    		[UIView animateWithDuration: 2
    			delay: 2
    			options: UIViewAnimationOptionCurveEaseInOut
    			animations: ^{
    				webView.alpha = 0;	//fade back out
    			}
    			completion: NULL
    		];
    	}
    
  2. [Visit Westhampton.] In the loadView: method of class ViewController, change preview.html to evacuation.html.

  3. In the loadView: method of class ViewController, change preview.html to crawl.html. (Look at crawl.html with Safari. In Firefox, remove the -webkit- prefixes, and change 40° to 25°.) Get rid of the fade in. Do not start with an alpha level of zero.

  4. To put an IMG in the web page, you’ll have to specify a base URL.
    	NSString *path = [[NSBundle mainBundle] bundlePath];
    	NSURL *baseURL = [NSURL fileURLWithPath: path];
    	[webView loadHTMLString: html baseURL: baseURL];
    

  5. Add a navigation bar with a Back button. First, put a navigation controller above the ViewController. In the application:didFinishLaunchingWithOptions: method of the application delegate,
    	ViewController *viewController =
    		[[ViewController alloc] initWithNibName: nil bundle: nil];
    
    	self.window.rootViewController =
    		[[UINavigationController alloc] initWithRootViewController: viewController];
    
    In the viewDidLoad method of the ViewController, after the call to [super viewDidLoad];,
    	self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
    		initWithTitle: @"Back"
    		style: UIBarButtonItemStylePlain
    		target: self.view
    		action: @selector(goBack)
    	];
    
    Why doesn’t the Back button go all the way back to the first page? Can you program around this? Can you disable the back button when you can’t go back any farther? See canGoBack. Can you make a Forward button? Can you display the title (or at least the URL) of the current page in the navigation bar? Can you let the user type a URL into a UITextField?

  6. Orson downloaded a Wikipedia article from @"http://en.m.wikipedia.org/wiki/The_Third_Man", where the first m stands for “mobile”. Remove the m. and send a User-Agent HTTP header in the HTTP request instead.
    	NSURL *url = [NSURL URLWithString: @"http://en.wikipedia.org/wiki/The_Third_Man"];
    
    	NSMutableURLRequest *request =
    		[NSMutableURLRequest requestWithURL: url];
    
    	//Download the web page in mobile format.
    	[request setValue: @"Mozilla/5.0 (iPhone)"
    		forHTTPHeaderField: @"User-Agent"];
    
    	NSURLResponse *response;
    	NSError *error;
    	NSData *data = [NSURLConnection sendSynchronousRequest: request
    		returningResponse: &response error: &error];
    
    	if (data == nil) {
    		NSLog(@"could not load URL %@: %@", url, error);
    	} else {
    		[webView loadData: data MIMEType: @"text/html"
    			textEncodingName: @"NSUTF8StringEncoding" baseURL: url];
    	}
    
    

    Here are five examples of this header.

    1. When I point iPhone Safari on the Simulator at the URL http://i5.nyu.edu:3001/ (specifying TCP/IP port number 3001 instead of the default 80), here is what the Safari says to the web server:

      GET / HTTP/1.1
      Host: i5.nyu.edu:3001
      User-Agent: Mozilla/5.0 (iPhone Simulator; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      Accept-Language: en-us
      Accept-Encoding: gzip, deflate
      Connection: keep-alive
      
      
    2. When I point iPhone Safari on an actual iPhone at the URL http://i5.nyu.edu:3001/ (specifying TCP/IP port number 3001 instead of the default 80), here is what the Safari says to the web server:

      GET / HTTP/1.1
      Host: i5.nyu.edu:3001
      User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_10 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8E600 Safari/6533.18.5
      Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
      Accept-Language: en-us
      Accept-Encoding: gzip, deflate
      Cookie: __utma=3868456.363797723.1320369206.1320369206.1320369206.1; __utmz=3868456.1320369206.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
      Connection: keep-alive
      
    3. When I point a NSData object at the URL http://i5.nyu.edu:3001/ here is what the NSData object says to the web server:
      GET / HTTP/1.1
      Host: i5.nyu.edu:3001
      User-Agent: Orson/1.0 CFNetwork/548.0.3 Darwin/10.8.0
      Accept: */*
      Accept-Language: en-us
      Accept-Encoding: gzip, deflate
      Connection: keep-alive
      
      
    4. When I point the web browser on my Android MB612 phone at the URL http://i5.nyu.edu:3001/ here is what the browser says to the web server:
      GET / HTTP/1.1
      Host: i5.nyu.edu:3001
      Accept-Encoding: gzip
      Accept-Language: en-US
      x-wap-profile: http://device.sprintpcs.com/Motorola/MOTOMB612/KRNSX41110.rdf
      User-Agent: Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; MB612 Build/KRNS-X4-1.1.10) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
      Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
      Accept-Charset: utf-8, iso-8859-1, utf-16, *;q=0.7
      
      
    5. When I point the Safari on a desktop Mac at the URL http://i5.nyu.edu:3001/ here is what the browser says to the web server:
      GET / HTTP/1.1
      Host: i5.nyu.edu:3001
      User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      Accept-Language: en-us
      Accept-Encoding: gzip, deflate
      Cookie: amlbcookie=724216000.36895.0000; AMAuthCookie=AQIC5wM2LY4SfcwPauQA9hv-LEaKnjfRHUzNtCk76c8jb6I.*AAJTSQACMDIAAlNLAAoxMjYyOTI3OTQwAAJTMQACMDY.*
      Connection: keep-alive