一、WebView
WebView就是一個內(nèi)嵌瀏覽器控件,在iOS中主要有兩種WebView:UIWebView和WKWebView,UIWebView是iOS2之后開始使用,WKWebView是在iOS8開始使用,毫無疑問WKWebView將逐步取代笨重的UIWebView。
WKWebView的優(yōu)點(diǎn):
WKWebView更多的支持HTML5的特性
WKWebView更快,占用內(nèi)存可能只有UIWebView的1/3 ~ 1/4
WKWebView高達(dá)60fps的滾動刷新率和豐富的內(nèi)置手勢
WKWebView具有Safari相同的JavaScript引擎
WKWebView增加了加載進(jìn)度屬性
盡管講了這么多WKWebView的優(yōu)點(diǎn),但還有很多項(xiàng)目還沒有升級到iOS8,UIWebView也還有學(xué)習(xí)的必要,也可以通過對比WKWebView和UIWebView的使用,加深理解。
注意:Xcode7禁用了明碼的HTTP請求(但不限HTTPS請求),應(yīng)該在info.plist里添加下面的字段,否則無法響應(yīng)HTTP請求
添加App Transport Security Settings,并在其中設(shè)置Allow Arbitrary Loads為YES
xcode7設(shè)置HTTP請求
二、UIWebView
1. UIWebView加載請求
- (void)simpleUIWebViewTest {// 1.創(chuàng)建webview,并設(shè)置大小,"20"為狀態(tài)欄高度CGFloatwidth =self.view.frame.size.width;CGFloatheight =self.view.frame.size.height -20;UIWebView*webView = [[UIWebViewalloc] initWithFrame:CGRectMake(0,20, width, height)];// 2.創(chuàng)建URLNSURL*url = [NSURLURLWithString:@"http://www.baidu.com"];// 3.創(chuàng)建RequestNSURLRequest*request =[NSURLRequestrequestWithURL:url];// 4.加載網(wǎng)頁[webView loadRequest:request];// 5.最后將webView添加到界面[self.view addSubview:webView];self.webView = webView;}
2. UIWebView的實(shí)用加載函數(shù)
//加載網(wǎng)絡(luò)請求- (void)loadRequest:(NSURLRequest*)request;/*
功能:加載本地HTML字符串
string為要加載的本地HTML字符串
baseURL用來確定htmlString的基準(zhǔn)地址,相當(dāng)于HTML的標(biāo)簽的作用,定義頁面中所有鏈接的默認(rèn)地址
*/- (void)loadHTMLString:(NSString*)string baseURL:(nullableNSURL*)baseURL;/* 加載二進(jìn)制數(shù)據(jù) */- (void)loadData:(NSData*)data MIMEType:(NSString*)MIMEType? ? ? ? ? ? ? ? ? ? characterEncodingName:(NSString*)characterEncodingName? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? baseURL:(NSURL*)baseURL;
下面是加載HTML字符串的例子
- (void)loadLocalHTMLFileToUIWebView{// 獲取本地html文件文件路徑NSString*localHTMLPageName =@"myPage";NSString*path = [[NSBundlemainBundle] pathForResource:localHTMLPageName ofType:@"html"];// 從html文件中讀取html字符串NSString*htmlString = [NSStringstringWithContentsOfFile:path? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? encoding:NSUTF8StringEncodingerror:NULL];// 加載本地HTML字符串[self.webView loadHTMLString:htmlString baseURL:[[NSBundlemainBundle] bundleURL]];}
UIWebView不僅可以加載HTML頁面,還支持pdf、word、txt、各種圖片等等的顯示。使用loadRequest方法加載的URL是pdf、word、txt、各種圖片的URL路徑,就可以加載對應(yīng)的文件,這里就不演示了。
3. UIWebView的網(wǎng)頁導(dǎo)航方法
我們?yōu)g覽網(wǎng)頁,時常會使用到的刷新網(wǎng)頁、前進(jìn)、后退等導(dǎo)航操作,UIWebView里面也有對應(yīng)的操作方法。
#pragma mark - 判斷屬性// 是否可以后退@property(nonatomic,readonly,getter=canGoBack)BOOLcanGoBack;// 是否可以向前@property(nonatomic,readonly,getter=canGoForward)BOOLcanGoForward;// 是否正在加載@property(nonatomic,readonly,getter=isLoading)BOOLloading;#pragma mark - 操作方法// 刷新網(wǎng)頁- (void)reload;// 停止加載網(wǎng)頁- (void)stopLoading;// 后退- (void)goBack;// 前進(jìn)- (void)goForward;
4. UIWebViewDelegate代理方法
一共有四個方法:
//是否允許加載網(wǎng)頁,也可獲取js要打開的url,通過截取此url可與js交互-(BOOL)webView:(UIWebView*)webViewshouldStartLoadWithRequest:(NSURLRequest*)requestnavigationType:(UIWebViewNavigationType)navigationType;//開始加載網(wǎng)頁-(void)webViewDidStartLoad:(UIWebView*)webView;//網(wǎng)頁加載完成-(void)webViewDidFinishLoad:(UIWebView*)webView;//網(wǎng)頁加載錯誤-(void)webView:(UIWebView*)webViewdidFailLoadWithError:(NSError*)error;
5. UIWebView和JavaScript交互的方法
主要有兩方面:JS執(zhí)行OC代碼、OC調(diào)取寫好的JS代碼
JS執(zhí)行OC代碼:
JS是不能執(zhí)行OC代碼的,但是可以變相的執(zhí)行,JS可以將要執(zhí)行的操作封裝到網(wǎng)絡(luò)請求里面,然后OC攔截這個請求,獲取URL里面的字符串解析即可,這里用到代理協(xié)議里面的一個方法
-(BOOL)webView:(UIWebView *)webView? ? shouldStartLoadWithRequest:(NSURLRequest *)request? ? ? ? ? ? ? ? navigationType:(UIWebViewNavigationType)navigationType
OC調(diào)取寫好的JS代碼:
用到WebView的一個方法stringByEvaluatingJavaScriptFromString
// 實(shí)現(xiàn)自動定位JS代碼, htmlLocationID為定位的位置(由JS開發(fā)人員給出),實(shí)現(xiàn)自動定位代碼,應(yīng)該在網(wǎng)頁加載完成之后再調(diào)用NSString*javascriptStr = [NSStringstringWithFormat:@"window.location.href = '#%@'",htmlLocationID];// webview執(zhí)行代碼[self.webView stringByEvaluatingJavaScriptFromString:javascriptStr];// 獲取網(wǎng)頁的titleNSString*title = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"];
6. UIWebView整合功能代碼
- (void)viewDidLoad{? ? [superviewDidLoad];? ? [selfinitWebView];}- (void)initWebView{// 1.創(chuàng)建webview,并設(shè)置大小,"20"為狀態(tài)欄高度CGFloatwidth =self.view.frame.size.width;CGFloatheight =self.view.frame.size.height -20;UIWebView*webView = [[UIWebViewalloc] initWithFrame:CGRectMake(0,20,width,height)];// 2.創(chuàng)建URLNSURL*url = [NSURLURLWithString:@"http://www.baidu.com"];// 3.創(chuàng)建RequestNSURLRequest*request =[NSURLRequestrequestWithURL:url];// 4.加載網(wǎng)頁[webView loadRequest:request];// 5.最后將webView添加到界面[self.view addSubview:webView];self.webView = webView;? ? webView.delegate =self;}#pragma mark 設(shè)置前進(jìn)后退按鈕狀態(tài)-(void)setBarButtonStatus{if(_webView.canGoBack) {? ? ? ? _barButtonBack.enabled =YES;? ? }else{? ? ? ? _barButtonBack.enabled =NO;? ? }if(_webView.canGoForward){? ? ? ? _barButtonForward.enabled =YES;? ? }else{? ? ? ? _barButtonForward.enabled =NO;? ? }}/*瀏覽器后退*/- (void)clickGoBackBtn{if(self.webView.canGoBack){? ? ? ? ? ? [self.webView goBack];? ? }}/*瀏覽器前進(jìn)*/- (void)clickGoForwardBtn{if(self.webView.canGoForward){? ? ? ? ? ? [self.webView goForward];? ? }}#pragma mark - UIWebViewDelegate代理方法#pragma mark 開始加載//是否允許加載網(wǎng)頁,也可獲取js要打開的url,通過截取此url可與js交互- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? navigationType:(UIWebViewNavigationType)navigationType{//截取URL,這里可以和JS進(jìn)行交互,但這里沒有寫,因?yàn)闀婕暗絁S的一些知識,增加復(fù)雜性NSString*urlString = [request.URL absoluteString];? ? urlString = [urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];NSArray*urlComps = [urlString componentsSeparatedByString:@"://"];NSLog(@"urlString=%@---urlComps=%@",urlString,urlComps);returnYES;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }//開始加載網(wǎng)頁- (void)webViewDidStartLoad:(UIWebView*)webView{//顯示網(wǎng)絡(luò)請求加載[UIApplicationsharedApplication].networkActivityIndicatorVisible =true;}//網(wǎng)頁加載完成- (void)webViewDidFinishLoad:(UIWebView*)webView{//隱藏網(wǎng)絡(luò)請求加載圖標(biāo)[UIApplicationsharedApplication].networkActivityIndicatorVisible =false;? ? [selfsetBarButtonStatus];//取得html內(nèi)容NSLog(@"%@",[self.webView stringByEvaluatingJavaScriptFromString:@"document.title"]);}//網(wǎng)頁加載錯誤- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error{UIAlertView*alert = [[UIAlertViewalloc] initWithTitle:@"系統(tǒng)提示"message:@"網(wǎng)絡(luò)連接發(fā)生錯誤!"delegate:selfcancelButtonTitle:nilotherButtonTitles:@"確定",nil];? ? ? ? [alert show];}
三、WKWebView
終于輪到WKWebView這個以后時代的主角出場了。要使用WKWebView需要導(dǎo)入 框架,你可以明顯地從下面看出我對WKWebView和UIWebView的區(qū)別對待,O(∩_∩)O哈哈~
1. WKWebView加載請求
和UIWebView用法完全一致:
#pragma mark - WKWebView簡單使用- (void)wkWebViewEasyUse{//1.創(chuàng)建WKWebViewCGFloatwidth =self.view.frame.size.width;CGFloatheight =self.view.frame.size.height -20;WKWebView*webView = [[WKWebViewalloc] initWithFrame:CGRectMake(0,20,width,height)];//2.創(chuàng)建URLNSURL*URL = [NSURLURLWithString:@"http://www.baidu.com"];//3.創(chuàng)建RequestNSURLRequest*request = [NSURLRequestrequestWithURL:URL];//4.加載Request[webView loadRequest:request];//5.添加到視圖self.webView = webView;? ? [self.view addSubview:webView];}
WKWebView顯示圖
2. WKWebView的實(shí)用加載方法
UIWebView有的,WKWebView都有,WKWebView多了一個加載文件方法,而且WKWebView的這些加載方法都有返回值。
/*加載請求*/- (WKNavigation*)loadRequest:(NSURLRequest*)request;/*加載本地HTML字符串*/- (WKNavigation*)loadHTMLString:(NSString*)string? ? ? ? ? ? ? ? ? ? ? ? ? baseURL:(nullableNSURL*)baseURL;/*加載本地文件*/- (WKNavigation*)loadFileURL:(NSURL*)url? ? ? allowingReadAccessToURL:(NSURL*)url;/* 加載二進(jìn)制數(shù)據(jù) */- (WKNavigation*)loadData:(NSData*)data? ? ? ? ? ? ? ? ? MIMEType:(NSString*)MIMEType? ? ? characterEncodingName:(NSString*)characterEncodingName? ? ? ? ? ? ? ? ? ? baseURL:(NSURL*)baseURL;
loadHTMLString方法的顯示效果會有一些區(qū)別,看下圖:
上面的是UIWebView加載效果,下面的是WKWebView加載的效果
我的HTML文件myPage.html如下:
Kenshin Cui's BlogI am Kenshin Cui
iOS Learn
估計(jì)兩種WebView加載HTML的默認(rèn)字體樣式是不一樣的,這里只是說一下
下面是加載本地文件的實(shí)例:
/* 模擬器調(diào)試加載mac本地文件 */- (void)loadLocalFile {// 1.創(chuàng)建webview,并設(shè)置大小,"20"為狀態(tài)欄高度CGFloatwidth =self.view.frame.size.width;CGFloatheight =self.view.frame.size.height -20;WKWebView*webView = [[WKWebViewalloc] initWithFrame:CGRectMake(0,20, width, height)];// 2.創(chuàng)建url? userName:電腦用戶名NSURL*url = [NSURLfileURLWithPath:@"/Users/userName/Desktop/bigIcon.png"];// 3.加載文件[webView loadFileURL:url allowingReadAccessToURL:url];// 最后將webView添加到界面[self.view addSubview:webView];}
模擬器加載本地文件效果圖
3. WKWebView的網(wǎng)頁導(dǎo)航方法
和UIWebView相差不大,多了返回值,多了一些屬性,也多了2個方法:
reloadFromOrigin,緩存加載
goToBackForwardListItem,跳轉(zhuǎn)到指定歷史頁面
下面是網(wǎng)頁導(dǎo)航方法列表:
@property(nonatomic,readonly)BOOLcanGoBack;@property(nonatomic,readonly)BOOLcanGoForward;@property(nonatomic,readonly,getter=isLoading)BOOLloading;- (WKNavigation*)goBack; - (WKNavigation*)goForward;- (WKNavigation*)reload; - (void)stopLoading;/* 加載進(jìn)度,取值范圍0~1 */@property(nonatomic,readonly)doubleestimatedProgress;/* 是否允許左右劃手勢導(dǎo)航,默認(rèn)不允許 */@property(nonatomic)BOOLallowsBackForwardNavigationGestures;/* 訪問歷史列表 */@property(nonatomic,readonly,strong)WKBackForwardList*backForwardList;/* 會比較網(wǎng)絡(luò)數(shù)據(jù)是否有變化,沒有變化則使用緩存,否則從新請求 */- (WKNavigation*)reloadFromOrigin;/* 比向前向后更強(qiáng)大,可以跳轉(zhuǎn)到某個指定歷史頁面 */- (WKNavigation*)goToBackForwardListItem:(WKBackForwardListItem*)item;
4. WKWebView的代理
UIWebView只有一個代理,但WKWebView有好幾個,但常用的有2個,
id navigationDelegate和id< WKUIDelegate > UIDelegate:
WKNavigationDelegate: 最常用,和UIWebViewDelegate功能類似,追蹤加載過程,有是否允許加載、開始加載、加載完成、加載失敗。
WKUIDelegate:UI界面相關(guān),原生控件支持,三種提示框:輸入、確認(rèn)、警告。
下面列出WKNavigationDelegate的常用代理方法
/* 1.在發(fā)送請求之前,決定是否跳轉(zhuǎn)? */-(void)webView:(WKWebView*)webViewdecidePolicyForNavigationAction:(WKNavigationAction*)navigationActiondecisionHandler:(void(^)(WKNavigationActionPolicy))decisionHandler;/* 2.頁面開始加載 */-(void)webView:(WKWebView*)webViewdidStartProvisionalNavigation:(WKNavigation*)navigation;/* 3.在收到服務(wù)器的響應(yīng)頭,根據(jù)response相關(guān)信息,決定是否跳轉(zhuǎn)。 */-(void)webView:(WKWebView*)webViewdecidePolicyForNavigationResponse:(WKNavigationResponse*)navigationResponsedecisionHandler:(void(^)(WKNavigationResponsePolicy))decisionHandler;/* 4.開始獲取到網(wǎng)頁內(nèi)容時返回,需要注入JS,在這里添加 */-(void)webView:(WKWebView*)webViewdidCommitNavigation:(WKNavigation*)navigation;/* 5.頁面加載完成之后調(diào)用 */-(void)webView:(WKWebView*)webViewdidFinishNavigation:(WKNavigation*)navigation;/* error - 頁面加載失敗時調(diào)用 */-(void)webView:(WKWebView*)webViewdidFailProvisionalNavigation:(WKNavigation*)navigation;/* 其他 - 處理服務(wù)器重定向Redirect */-(void)webView:(WKWebView*)webViewdidReceiveServerRedirectForProvisionalNavigation:(WKNavigation*)navigation;
我們看看WKUIDelegate的幾個代理方法,雖然不是必須實(shí)現(xiàn)的,但是如果我們的頁面中有調(diào)用了JS的alert、confirm、prompt方法,我們應(yīng)該實(shí)現(xiàn)下面這幾個代理方法,然后在這里調(diào)用iOS的彈出窗,因?yàn)槭褂肳KWebView后,HTML中的alert、confirm、prompt方法調(diào)用是不會再彈出窗口了
下面列出WKUIDelegate的常用代理方法:
/* 輸入框,頁面中有調(diào)用JS的 prompt 方法就會調(diào)用該方法 */-(void)webView:(WKWebView*)webViewrunJavaScriptTextInputPanelWithPrompt:(NSString*)promptdefaultText:(nullableNSString*)defaultTextinitiatedByFrame:(WKFrameInfo*)framecompletionHandler:(void(^)(NSString *result))completionHandler;/* 確認(rèn)框,頁面中有調(diào)用JS的 confirm 方法就會調(diào)用該方法 */-(void)webView:(WKWebView*)webViewrunJavaScriptConfirmPanelWithMessage:(NSString*)messageinitiatedByFrame:(WKFrameInfo*)framecompletionHandler:(void(^)(BOOL result))completionHandler;/* 警告框,頁面中有調(diào)用JS的 alert 方法就會調(diào)用該方法 */-(void)webView:(WKWebView*)webViewrunJavaScriptAlertPanelWithMessage:(NSString*)messageinitiatedByFrame:(WKFrameInfo*)framecompletionHandler:(void(^)(void))completionHandler;