你的位置:首页 > 操作系统

[操作系统]UIWebView 操作


网络开发中,当公司已经使用 HTML5 技术实现适应 Android 和 iOS 跨平台的网页时,这时往往需要我们 iOS 平台能够嵌入网页并进行各种交互,那我们应该怎么做来实现这种需求呢?

这里我们考虑的方案就是:使用 UIWebView 网页控件

本随笔简单介绍如何使用 UIWebView 网页控件:

(1)简单浏览器

  • file://WhatsNewIniPhoneOS.pdf 读取本地资源文件

  • http://www.apple.com 读取网站内容

  • KenmuHuang 读取百度搜索网站相关查询内容

(2)页面交互

(3)页面调用 OC 方法

 

效果如下:

 

 

ViewController.h

1 #import <UIKit/UIKit.h>2 3 @interface ViewController : UITableViewController4 @property (copy, nonatomic) NSArray *arrSampleName;5 6 - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName;7 8 @end 

ViewController.m

 1 #import "ViewController.h" 2 #import "SimpleBrowserViewController.h" 3 #import "PageInteractionViewController.h" 4 #import "PageCallOCFunctionViewController.h" 5  6 @interface ViewController () 7 - (void)layoutUI; 8 @end 9 10 @implementation ViewController11 - (void)viewDidLoad {12   [super viewDidLoad];13   14   [self layoutUI];15 }16 17 - (void)didReceiveMemoryWarning {18   [super didReceiveMemoryWarning];19   // Dispose of any resources that can be recreated.20 }21 22 - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName {23   if (self = [super initWithStyle:UITableViewStyleGrouped]) {24     self.navigationItem.title = @"UIWebView 操作";25     self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil];26     27     _arrSampleName = arrSampleName;28   }29   return self;30 }31 32 - (void)layoutUI {33   34 }35 36 #pragma mark - UITableViewController相关方法重写37 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {38   return 0.1;39 }40 41 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {42   return 1;43 }44 45 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {46   return [_arrSampleName count];47 }48 49 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {50   static NSString *cellIdentifier = @"cell";51   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];52   if (!cell) {53     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];54   }55   cell.textLabel.text = _arrSampleName[indexPath.row];56   return cell;57 }58 59 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {60   switch (indexPath.row) {61     case 0: {62       SimpleBrowserViewController *simpleBrowserVC = [SimpleBrowserViewController new];63       [self.navigationController pushViewController:simpleBrowserVC animated:YES];64       break;65     }66     case 1: {67       PageInteractionViewController *pageInteractionVC = [PageInteractionViewController new];68       [self.navigationController pushViewController:pageInteractionVC animated:YES];69       break;70     }71     case 2: {72       PageCallOCFunctionViewController *pageCallOCFunctionVC = [PageCallOCFunctionViewController new];73       [self.navigationController pushViewController:pageCallOCFunctionVC animated:YES];74       break;75     }76     default:77       break;78   }79 }80 81 @end 

PrefixHeader.pch

1 #define kTitleOfSimpleBrowser @"简单浏览器"2 #define kTitleOfPageInteraction @"页面交互"3 #define kTitleOfPageCallOCFunction @"页面调用 OC 方法"4 5 #define kApplication [UIApplication sharedApplication] 

SimpleBrowserViewController.h

 1 #import <UIKit/UIKit.h> 2  3 @interface SimpleBrowserViewController : UIViewController <UISearchBarDelegate, UIWebViewDelegate> 4 @property (strong, nonatomic) UISearchBar *searchBar; 5 @property (strong, nonatomic) UIWebView *webView; 6 @property (strong, nonatomic) UIToolbar *toolbar; 7 @property (strong, nonatomic) UIBarButtonItem *barBtnBack; 8 @property (strong, nonatomic) UIBarButtonItem *barBtnForward; 9 10 @end 

SimpleBrowserViewController.m

 1 #import "SimpleBrowserViewController.h" 2  3 @interface SimpleBrowserViewController () 4 - (void)webViewBack; 5 - (void)webViewForward; 6 - (void)layoutUI; 7 - (void)sendRequest:(NSString *)requestURLStr; 8 - (void)changeBarButtonStatus; 9 @end 10  11 @implementation SimpleBrowserViewController 12  13 - (void)viewDidLoad { 14   [super viewDidLoad]; 15    16   [self layoutUI]; 17 } 18  19 - (void)didReceiveMemoryWarning { 20   [super didReceiveMemoryWarning]; 21   // Dispose of any resources that can be recreated. 22 } 23  24 - (void)webViewBack { 25   [_webView goBack]; 26 } 27  28 - (void)webViewForward { 29   [_webView goForward]; 30 } 31  32 - (void)layoutUI { 33   self.navigationItem.title = kTitleOfSimpleBrowser; 34   self.automaticallyAdjustsScrollViewInsets = NO; //是否自动适应滚动视图的内嵌入;默认为YES,这里设置为NO,避免网页控件中_UIWebViewScrollView的UIWebBrowserView位置偏移 35    36   CGRect rect = [[UIScreen mainScreen] bounds]; 37   static const CGFloat heightOfStatusBarAndNavigationBar = 64.0; 38   CGFloat widthOfScreen = rect.size.width; 39   CGFloat heightOfScreen = rect.size.height; 40    41   //添加搜索栏 42   _searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0, heightOfStatusBarAndNavigationBar, widthOfScreen, 44.0)]; 43   _searchBar.delegate = self; 44   _searchBar.placeholder = @"请输入以file://或http开头的地址"; 45   [self.view addSubview:_searchBar]; 46    47   //添加工具栏和左右按钮(回退和前进) 48   _toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, heightOfScreen - 44.0, 49                              widthOfScreen, 44.0)]; 50   rect = CGRectMake(0.0, 0.0, 32.0, 32.0); 51   UIButton *btnBack = [UIButton buttonWithType:UIButtonTypeCustom]; 52   btnBack.frame = rect; 53   [btnBack setImage:[UIImage imageNamed:@"LastPageNormal"] forState:UIControlStateNormal]; 54   [btnBack setImage:[UIImage imageNamed:@"LastPageDisabled"] forState:UIControlStateDisabled]; 55   [btnBack addTarget:self 56         action:@selector(webViewBack) 57    forControlEvents:UIControlEventTouchUpInside]; 58   _barBtnBack = [[UIBarButtonItem alloc] initWithCustomView:btnBack]; 59   _barBtnBack.enabled = NO; 60    61   UIBarButtonItem *barBtnSpacing=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; 62    63   UIButton *btnForward = [UIButton buttonWithType:UIButtonTypeCustom]; 64   btnForward.frame = rect; 65   [btnForward setImage:[UIImage imageNamed:@"NextPageNormal"] forState:UIControlStateNormal]; 66   [btnForward setImage:[UIImage imageNamed:@"NextPageDisabled"] forState:UIControlStateDisabled]; 67   [btnForward addTarget:self 68           action:@selector(webViewForward) 69      forControlEvents:UIControlEventTouchUpInside]; 70   _barBtnForward = [[UIBarButtonItem alloc] initWithCustomView:btnForward]; 71   _barBtnForward.enabled = NO; 72    73   _toolbar.items = @[ _barBtnBack, barBtnSpacing, _barBtnForward ]; 74   [self.view addSubview:_toolbar]; 75    76   //添加网页控件 77   CGFloat heightOfWebView = heightOfScreen - _searchBar.frame.origin.y - _searchBar.frame.size.height - _toolbar.frame.size.height; 78   _webView = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, heightOfStatusBarAndNavigationBar + _searchBar.frame.size.height, 79                               widthOfScreen, heightOfWebView)]; 80   _webView.dataDetectorTypes = UIDataDetectorTypeAll; 81   _webView.delegate = self; 82   [self.view addSubview:_webView]; 83 } 84  85 - (void)sendRequest:(NSString *)requestURLStr { 86   if (requestURLStr.length > 0) { 87     NSURL *requestURL; 88      89     //加载bundle中的文件;网页控件打开本地pdf、word文件依靠的并不是他自身解析,而是依靠MIME Type识别文件类型并调用对应应用打开 90     if ([requestURLStr hasPrefix:@"file://"]) { 91       NSRange range = [requestURLStr rangeOfString:@"file://"]; 92       NSString *fileName = [requestURLStr substringFromIndex:range.length]; 93       requestURL = [[NSBundle mainBundle] URLForResource:fileName 94                          withExtension:nil]; 95     } else { 96       //加载百度搜索网站的内容 97       if (![requestURLStr hasPrefix:@"http"]) { 98         requestURLStr = [NSString stringWithFormat:@"https://www.baidu.com/s?wd=%@", requestURLStr]; 99       }100       //最终加载的还是HTTP或者HTTPS协议的网站内容,进行编码操作101       requestURLStr = [requestURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];102       requestURL = [NSURL URLWithString:requestURLStr];103     }104     105     //加载请求地址内容106     [_webView loadRequest:[NSURLRequest requestWithURL:requestURL]];107   }108 }109 110 - (void)changeBarButtonStatus {111   _barBtnBack.enabled = _webView.canGoBack;112   _barBtnForward.enabled = _webView.canGoForward;113 }114 115 #pragma mark - UIWebViewDelegate116 - (void)webViewDidStartLoad:(UIWebView *)webView {117   kApplication.networkActivityIndicatorVisible = YES;118 }119 120 - (void)webViewDidFinishLoad:(UIWebView *)webView {121   kApplication.networkActivityIndicatorVisible = NO;122   [self changeBarButtonStatus];123 }124 125 - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {126   NSLog(@"Error: %@", error);127   kApplication.networkActivityIndicatorVisible = NO;128   UIAlertView *alertVCustom = [[UIAlertView alloc] initWithTitle:@"提示信息"129                              message:@"网络连接错误"130                              delegate:nil131                         cancelButtonTitle:@"确定"132                          otherButtonTitles:nil, nil];133   [alertVCustom show];134 }135 136 #pragma mark - UISearchBarDelegate137 - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {138   [self sendRequest:searchBar.text];139   [_searchBar resignFirstResponder];140 }141 142 @end 

PageInteractionViewController.h

1 #import <UIKit/UIKit.h>2 3 @interface PageInteractionViewController : UIViewController<UIWebViewDelegate>4 @property (strong, nonatomic) UIWebView *webView;5 6 @end 

PageInteractionViewController.m

 1 #import "PageInteractionViewController.h" 2  3 @interface PageInteractionViewController () 4 - (void)layoutUI; 5 - (void)sendRequest; 6 @end 7  8 @implementation PageInteractionViewController 9 10 - (void)viewDidLoad {11   [super viewDidLoad];12   13   [self layoutUI];14   15   [self sendRequest];16 }17 18 - (void)didReceiveMemoryWarning {19   [super didReceiveMemoryWarning];20   // Dispose of any resources that can be recreated.21 }22 23 - (void)layoutUI {24   self.navigationItem.title = kTitleOfPageInteraction;25   self.automaticallyAdjustsScrollViewInsets = NO; //是否自动适应滚动视图的内嵌入;默认为YES,这里设置为NO,避免网页控件中_UIWebViewScrollView的UIWebBrowserView位置偏移26   27   CGRect rect = [[UIScreen mainScreen] bounds];28   static const CGFloat heightOfStatusBarAndNavigationBar = 64.0;29   //添加网页控件30   _webView = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, heightOfStatusBarAndNavigationBar,31                              rect.size.width, rect.size.height - heightOfStatusBarAndNavigationBar)];32   _webView.dataDetectorTypes = UIDataDetectorTypeAll;33   _webView.delegate = self;34   self.automaticallyAdjustsScrollViewInsets = NO;35   [self.view addSubview:_webView];36 }37 38 - (void)sendRequest {39   NSString *htmlStr=@"<html>\40               <head><title>KenmuHuang's Blog</title></head>\41               <body style=\"color:#0044AA;\">\42                 <h3 id=\"header\">I'm KenmuHuang</h3>\43                 <p>More coding, more thinking. Stay hungry, stay foolish.</p>\44                 <span>http://www.cnblogs.com/huangjianwu/</span>\45               </body>\46             </html>";47   [_webView loadHTMLString:htmlStr baseURL:nil];48 }49 50 #pragma mark - UIWebViewDelegate51 - (void)webViewDidStartLoad:(UIWebView *)webView {52   kApplication.networkActivityIndicatorVisible = YES;53 }54 55 - (void)webViewDidFinishLoad:(UIWebView *)webView {56   kApplication.networkActivityIndicatorVisible = NO;57   NSLog(@"%@",[_webView stringByEvaluatingJavaScriptFromString:@"document.title"]); //打印内容为html的title标签内容:KenmuHuang's Blog58   NSLog(@"%@",[_webView stringByEvaluatingJavaScriptFromString:@"document.getElementById('header').innerHTML='KenmuHuang\\'s Blog';"]); //必须使用双反斜杆来转译单引号59 }60 61 - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {62   NSLog(@"Error: %@", error);63   kApplication.networkActivityIndicatorVisible = NO;64   UIAlertView *alertVCustom = [[UIAlertView alloc] initWithTitle:@"提示信息"65                              message:@"网络连接错误"66                              delegate:nil67                         cancelButtonTitle:@"确定"68                          otherButtonTitles:nil, nil];69   [alertVCustom show];70 }71 72 @end 

RedirectURL.js

 1 function showSheet(title, cancelButtonTitle, destructiveButtonTitle, otherButtonTitle) { 2   var url = 'KMActionSheet://?'; 3   var paramas = title + '&' + cancelButtonTitle + '&' + destructiveButtonTitle; 4   if(otherButtonTitle) { 5     paramas += '&' + otherButtonTitle; 6   } 7   window.location.href = url + encodeURIComponent(paramas); 8 } 9 10 var header = document.getElementById('header');11 if(header) {12   header.onclick = function(){13     showSheet('系统提示', '取消', '确定', null);14   };15 } 

PageCallOCFunctionViewController.h

1 #import <UIKit/UIKit.h>2 3 @interface PageCallOCFunctionViewController : UIViewController<UIWebViewDelegate>4 @property (strong, nonatomic) UIWebView *webView;5 6 @end 

PageCallOCFunctionViewController.m

 1 #import "PageCallOCFunctionViewController.h" 2  3 @interface PageCallOCFunctionViewController () 4 - (void)layoutUI; 5 - (void)sendRequest; 6 - (void)showActionSheetWithTitle:(NSString *)title cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle otherButtonTitle:(NSString *)otherButtonTitle; 7 @end 8  9 @implementation PageCallOCFunctionViewController 10  11 - (void)viewDidLoad { 12   [super viewDidLoad]; 13    14   [self layoutUI]; 15    16   [self sendRequest]; 17 } 18  19 - (void)didReceiveMemoryWarning { 20   [super didReceiveMemoryWarning]; 21   // Dispose of any resources that can be recreated. 22 } 23  24 - (void)layoutUI { 25   self.navigationItem.title = kTitleOfPageCallOCFunction; 26   self.automaticallyAdjustsScrollViewInsets = NO; //是否自动适应滚动视图的内嵌入;默认为YES,这里设置为NO,避免网页控件中_UIWebViewScrollView的UIWebBrowserView位置偏移 27    28   CGRect rect = [[UIScreen mainScreen] bounds]; 29   static const CGFloat heightOfStatusBarAndNavigationBar = 64.0; 30   //添加网页控件 31   _webView = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, heightOfStatusBarAndNavigationBar, 32                              rect.size.width, rect.size.height - heightOfStatusBarAndNavigationBar)]; 33   _webView.dataDetectorTypes = UIDataDetectorTypeAll; 34   _webView.delegate = self; 35   self.automaticallyAdjustsScrollViewInsets = NO; 36   [self.view addSubview:_webView]; 37 } 38  39 - (void)sendRequest { 40   NSString *htmlStr=@"<html>\ 41   <head><title>KenmuHuang's Blog</title></head>\ 42   <body style=\"color:#0044AA;\">\ 43   <h3 id=\"header\">I'm KenmuHuang, click me to show action sheet.</h3>\ 44   <p>More coding, more thinking. Stay hungry, stay foolish.</p>\ 45   <span>http://www.cnblogs.com/huangjianwu/</span>\ 46   </body>\ 47   </html>"; 48   [_webView loadHTMLString:htmlStr baseURL:nil]; 49 } 50  51 - (void)showActionSheetWithTitle:(NSString *)title cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle otherButtonTitle:(NSString *)otherButtonTitle{ 52   UIActionSheet *actionSheet=[[UIActionSheet alloc] initWithTitle:title 53                              delegate:nil 54                          cancelButtonTitle:cancelButtonTitle 55                        destructiveButtonTitle:destructiveButtonTitle 56                          otherButtonTitles:otherButtonTitle, nil]; 57   [actionSheet showInView:self.view]; 58 } 59  60 #pragma mark - UIWebViewDelegate 61 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { 62   BOOL isStartLoad = YES; 63   if ([request.URL.scheme isEqualToString:@"kmactionsheet"]) { //request.URL.scheme 返回全小写的内容 64     NSString *paramContent = request.URL.query; 65     NSArray *arrParam = [[paramContent stringByRemovingPercentEncoding] componentsSeparatedByString:@"&"]; 66     NSString *otherButtonTitle = nil; 67     if (arrParam.count > 3) { 68       otherButtonTitle = arrParam[3]; 69     } 70      71     [self showActionSheetWithTitle:arrParam[0] 72           cancelButtonTitle:arrParam[1] 73         destructiveButtonTitle:arrParam[2] 74            otherButtonTitle:otherButtonTitle]; 75     isStartLoad = NO; 76   } 77   return isStartLoad; 78 } 79  80 - (void)webViewDidStartLoad:(UIWebView *)webView { 81   kApplication.networkActivityIndicatorVisible = YES; 82 } 83  84 - (void)webViewDidFinishLoad:(UIWebView *)webView { 85   kApplication.networkActivityIndicatorVisible = NO; 86    87   //加载用于重定向地址的JavaScript内容 88   NSString *jsPath = [[NSBundle mainBundle] pathForResource:@"RedirectURL.js" ofType:nil]; 89   NSString *jsContent = [NSString stringWithContentsOfFile:jsPath 90                           encoding:NSUTF8StringEncoding 91                             error:nil]; 92   [_webView stringByEvaluatingJavaScriptFromString:jsContent]; 93 } 94  95 - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { 96   NSLog(@"Error: %@", error); 97   kApplication.networkActivityIndicatorVisible = NO; 98   UIAlertView *alertVCustom = [[UIAlertView alloc] initWithTitle:@"提示信息" 99                              message:@"网络连接错误"100                              delegate:nil101                         cancelButtonTitle:@"确定"102                          otherButtonTitles:nil, nil];103   [alertVCustom show];104 }105 106 @end 

AppDelegate.h

1 #import <UIKit/UIKit.h>2 3 @interface AppDelegate : UIResponder <UIApplicationDelegate>4 5 @property (strong, nonatomic) UIWindow *window;6 @property (strong, nonatomic) UINavigationController *navigationController;7 8 @end 

AppDelegate.m

 1 #import "AppDelegate.h" 2 #import "ViewController.h" 3  4 @interface AppDelegate () 5  6 @end 7  8 @implementation AppDelegate 9 10 11 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {12   _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];13   ViewController *viewController = [[ViewController alloc]14                    initWithSampleNameArray:@[ kTitleOfSimpleBrowser,15                                  kTitleOfPageInteraction,16                                  kTitleOfPageCallOCFunction ]];17   _navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];18   _window.rootViewController = _navigationController;19   //[_window addSubview:_navigationController.view]; //当_window.rootViewController关联时,这一句可有可无20   [_window makeKeyAndVisible];21   return YES;22 }23 24 - (void)applicationWillResignActive:(UIApplication *)application {25 }26 27 - (void)applicationDidEnterBackground:(UIApplication *)application {28 }29 30 - (void)applicationWillEnterForeground:(UIApplication *)application {31 }32 33 - (void)applicationDidBecomeActive:(UIApplication *)application {34 }35 36 - (void)applicationWillTerminate:(UIApplication *)application {37 }38 39 @end