iOS學習筆記14 網路(三)WebView

執著丶執念發表於2018-06-02

###一、WebView WebView就是一個內嵌瀏覽器控制元件,在iOS中主要有兩種WebView:UIWebViewWKWebView,UIWebView是iOS2之後開始使用,WKWebView是在iOS8開始使用,毫無疑問WKWebView將逐步取代笨重的UIWebView。

######WKWebView的優點:

  1. WKWebView更多的支援HTML5的特性
  2. WKWebView更快,佔用記憶體可能只有UIWebView的1/3 ~ 1/4
  3. WKWebView高達60fps的滾動重新整理率和豐富的內建手勢
  4. WKWebView具有Safari相同的JavaScript引擎
  5. WKWebView增加了載入進度屬性

儘管講了這麼多WKWebView的優點,但還有很多專案還沒有升級到iOS8,UIWebView也還有學習的必要,也可以通過對比WKWebView和UIWebView的使用,加深理解。

注意:Xcode7禁用了明碼的HTTP請求(但不限HTTPS請求),應該在info.plist裡新增下面的欄位,否則無法響應HTTP請求 ######新增App Transport Security Settings,並在其中設定Allow Arbitrary LoadsYES

xcode7設定HTTP請求

###二、UIWebView ####1. UIWebView載入請求

- (void)simpleUIWebViewTest {
    // 1.建立webview,並設定大小,"20"為狀態列高度
    CGFloat width = self.view.frame.size.width;
    CGFloat height = self.view.frame.size.height - 20;
    UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 20, width, height)];
    // 2.建立URL
    NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
    // 3.建立Request
    NSURLRequest *request =[NSURLRequest requestWithURL:url];
    // 4.載入網頁
    [webView loadRequest:request];
    // 5.最後將webView新增到介面
    [self.view addSubview:webView];
    self.webView = webView;
}
複製程式碼

####2. UIWebView的實用載入函式

//載入網路請求
- (void)loadRequest:(NSURLRequest *)request;
 
/* 
    功能:載入本地HTML字串
    string為要載入的本地HTML字串
    baseURL用來確定htmlString的基準地址,相當於HTML的<base>標籤的作用,定義頁面中所有連結的預設地址
*/
- (void)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
/* 載入二進位制資料 */
- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType 
                   characterEncodingName:(NSString *)characterEncodingName 
                                 baseURL:(NSURL *)baseURL;
複製程式碼

######下面是載入HTML字串的例子

- (void)loadLocalHTMLFileToUIWebView{
    // 獲取本地html檔案檔案路徑
    NSString *localHTMLPageName = @"myPage";
    NSString *path = [[NSBundle mainBundle] pathForResource:localHTMLPageName ofType:@"html"];
    // 從html檔案中讀取html字串
    NSString *htmlString = [NSString stringWithContentsOfFile:path 
                                                     encoding:NSUTF8StringEncoding 
                                                        error:NULL];
    // 載入本地HTML字串
    [self.webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
}
複製程式碼

UIWebView不僅可以載入HTML頁面,還支援pdf、word、txt、各種圖片等等的顯示。使用loadRequest方法載入的URL是pdf、word、txt、各種圖片的URL路徑,就可以載入對應的檔案,這裡就不演示了。

####3. UIWebView的網頁導航方法 我們瀏覽網頁,時常會使用到的重新整理網頁、前進、後退等導航操作,UIWebView裡面也有對應的操作方法。

#pragma mark - 判斷屬性
// 是否可以後退
@property (nonatomic, readonly, getter=canGoBack) BOOL canGoBack;
// 是否可以向前
@property (nonatomic, readonly, getter=canGoForward) BOOL canGoForward;
// 是否正在載入
@property (nonatomic, readonly, getter=isLoading) BOOL loading;

#pragma mark - 操作方法
// 重新整理網頁
- (void)reload;
// 停止載入網頁
- (void)stopLoading;
// 後退
- (void)goBack;
// 前進
- (void)goForward;
複製程式碼

####4. UIWebViewDelegate代理方法 ######一共有四個方法:

//是否允許載入網頁,也可獲取js要開啟的url,通過擷取此url可與js互動
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request 
												 navigationType:(UIWebViewNavigationType)navigationType;
//開始載入網頁
- (void)webViewDidStartLoad:(UIWebView *)webView;
//網頁載入完成
- (void)webViewDidFinishLoad:(UIWebView *)webView;
//網頁載入錯誤
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;
複製程式碼

####5. UIWebView和JavaScript互動的方法 主要有兩方面:JS執行OC程式碼、OC調取寫好的JS程式碼

  • JS執行OC程式碼: JS是不能執行OC程式碼的,但是可以變相的執行,JS可以將要執行的操作封裝到網路請求裡面,然後OC攔截這個請求,獲取URL裡面的字串解析即可,這裡用到代理協議裡面的一個方法
- (BOOL)webView:(UIWebView *)webView  
   shouldStartLoadWithRequest:(NSURLRequest *)request  
               navigationType:(UIWebViewNavigationType)navigationType
複製程式碼
  • OC調取寫好的JS程式碼: 用到WebView的一個方法stringByEvaluatingJavaScriptFromString
// 實現自動定位JS程式碼, htmlLocationID為定位的位置(由JS開發人員給出),實現自動定位程式碼,應該在網頁載入完成之後再呼叫
NSString *javascriptStr = [NSString stringWithFormat:@"window.location.href = '#%@'",htmlLocationID];
// webview執行程式碼
[self.webView stringByEvaluatingJavaScriptFromString:javascriptStr];
// 獲取網頁的title
NSString *title = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"];
複製程式碼

####6. UIWebView整合功能程式碼

- (void)viewDidLoad
{
	[super viewDidLoad];
	[self initWebView];
}
- (void)initWebView{
    // 1.建立webview,並設定大小,"20"為狀態列高度
    CGFloat width = self.view.frame.size.width;
    CGFloat height = self.view.frame.size.height - 20;
    UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0,20,width,height)];
    // 2.建立URL
    NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
    // 3.建立Request
    NSURLRequest *request =[NSURLRequest requestWithURL:url];
    // 4.載入網頁
    [webView loadRequest:request];
    // 5.最後將webView新增到介面
    [self.view addSubview:webView];
    self.webView = webView;
    webView.delegate = self;
}
#pragma mark 設定前進後退按鈕狀態
-(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];
	}
}
/*瀏覽器前進*/
- (void)clickGoForwardBtn{
	if(self.webView.canGoForward){	
		[self.webView goForward];
	}
}
#pragma mark - UIWebViewDelegate代理方法
#pragma mark 開始載入
//是否允許載入網頁,也可獲取js要開啟的url,通過擷取此url可與js互動
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request 
						       navigationType:(UIWebViewNavigationType)navigationType
{
    //擷取URL,這裡可以和JS進行互動,但這裡沒有寫,因為會涉及到JS的一些知識,增加複雜性
    NSString *urlString = [request.URL absoluteString];
    urlString = [urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSArray *urlComps = [urlString componentsSeparatedByString:@"://"];
    NSLog(@"urlString=%@---urlComps=%@",urlString,urlComps);
	return YES;												
}
//開始載入網頁
- (void)webViewDidStartLoad:(UIWebView *)webView{
	//顯示網路請求載入    
	[UIApplication sharedApplication].networkActivityIndicatorVisible = true;
}
//網頁載入完成
- (void)webViewDidFinishLoad:(UIWebView *)webView{
	//隱藏網路請求載入圖示    
	[UIApplication sharedApplication].networkActivityIndicatorVisible = false;
	[self setBarButtonStatus];
    //取得html內容
    NSLog(@"%@",[self.webView stringByEvaluatingJavaScriptFromString:@"document.title"]);
}
//網頁載入錯誤
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
	UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"系統提示" 
                                                    message:@"網路連線發生錯誤!" 
				                                   delegate:self 
                                          cancelButtonTitle:nil 
                                          otherButtonTitles:@"確定", nil];    
	[alert show];
}
複製程式碼

###三、WKWebView 終於輪到WKWebView這個以後時代的主角出場了。要使用WKWebView需要匯入 <WebKit/WebKit.h>框架,你可以明顯地從下面看出我對WKWebView和UIWebView的區別對待,O(∩_∩)O哈哈~

####1. WKWebView載入請求 ######和UIWebView用法完全一致:

#pragma mark - WKWebView簡單使用
- (void)wkWebViewEasyUse
{
    //1.建立WKWebView
    CGFloat width = self.view.frame.size.width;
    CGFloat height = self.view.frame.size.height - 20;
    WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0,20,width,height)];
    //2.建立URL
    NSURL *URL = [NSURL URLWithString:@"http://www.baidu.com"];
    //3.建立Request
    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
    //4.載入Request
    [webView loadRequest:request];
    //5.新增到檢視
    self.webView = webView;
    [self.view addSubview:webView];
}
複製程式碼

WKWebView顯示圖

####2. WKWebView的實用載入方法 UIWebView有的,WKWebView都有,WKWebView多了一個載入檔案方法,而且WKWebView的這些載入方法都有返回值。

/*載入請求*/
- (WKNavigation *)loadRequest:(NSURLRequest *)request;
/*載入本地HTML字串*/
- (WKNavigation *)loadHTMLString:(NSString *)string 
                         baseURL:(nullable NSURL *)baseURL;
/*載入本地檔案*/
- (WKNavigation *)loadFileURL:(NSURL*)url 
      allowingReadAccessToURL:(NSURL*)url;
/* 載入二進位制資料 */
- (WKNavigation *)loadData:(NSData *)data 
                  MIMEType:(NSString *)MIMEType 
     characterEncodingName:(NSString *)characterEncodingName 
                   baseURL:(NSURL *)baseURL;
複製程式碼

#####loadHTMLString方法的顯示效果會有一些區別,看下圖:

上面的是UIWebView載入效果,下面的是WKWebView載入的效果

######我的HTML檔案myPage.html如下:

<html>
    <head><title>Kenshin Cui's Blog</title></head>
    <body style="color:#0092FF;">
        <h1 id="header">I am Kenshin Cui</h1>
        <p>iOS Learn</p>
    </body>
</html>
複製程式碼

估計兩種WebView載入HTML的預設字型樣式是不一樣的,這裡只是說一下

######下面是載入本地檔案的例項:

/* 模擬器除錯載入mac本地檔案 */
- (void)loadLocalFile {
    // 1.建立webview,並設定大小,"20"為狀態列高度
    CGFloat width = self.view.frame.size.width;
    CGFloat height = self.view.frame.size.height - 20;
    WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 20, width, height)];
    // 2.建立url  userName:電腦使用者名稱
    NSURL *url = [NSURL fileURLWithPath:@"/Users/userName/Desktop/bigIcon.png"];
    // 3.載入檔案
    [webView loadFileURL:url allowingReadAccessToURL:url];
    // 最後將webView新增到介面
    [self.view addSubview:webView];
}
複製程式碼

模擬器載入本地檔案效果圖

####3. WKWebView的網頁導航方法 和UIWebView相差不大,多了返回值,多了一些屬性,也多了2個方法:

  • reloadFromOrigin,快取載入
  • goToBackForwardListItem,跳轉到指定歷史頁面

######下面是網頁導航方法列表:

@property (nonatomic, readonly) BOOL canGoBack;
@property (nonatomic, readonly) BOOL canGoForward;
@property (nonatomic, readonly, getter=isLoading) BOOL loading;
- (WKNavigation *)goBack; 
- (WKNavigation *)goForward;
- (WKNavigation *)reload; 
- (void)stopLoading; 

/* 載入進度,取值範圍0~1 */
@property (nonatomic, readonly) double estimatedProgress;
/* 是否允許左右劃手勢導航,預設不允許 */
@property (nonatomic) BOOL allowsBackForwardNavigationGestures;
/* 訪問歷史列表 */
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;
/* 會比較網路資料是否有變化,沒有變化則使用快取,否則從新請求 */
- (WKNavigation *)reloadFromOrigin;
/* 比向前向後更強大,可以跳轉到某個指定歷史頁面 */
- (WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;
複製程式碼

####4. WKWebView的代理 UIWebView只有一個代理,但WKWebView有好幾個,但常用的有2個, id<WKNavigationDelegate> navigationDelegateid< WKUIDelegate > UIDelegate

  • WKNavigationDelegate: 最常用,和UIWebViewDelegate功能類似,追蹤載入過程,有是否允許載入、開始載入、載入完成、載入失敗。
  • WKUIDelegate:UI介面相關,原生控制元件支援,三種提示框:輸入、確認、警告。

######下面列出WKNavigationDelegate的常用代理方法

/* 1.在傳送請求之前,決定是否跳轉  */
- (void)webView:(WKWebView *)webView 
        decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction 
                        decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
/* 2.頁面開始載入 */
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
/* 3.在收到伺服器的響應頭,根據response相關資訊,決定是否跳轉。 */
- (void)webView:(WKWebView *)webView 
        decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse 
                          decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
/* 4.開始獲取到網頁內容時返回,需要注入JS,在這裡新增 */
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
/* 5.頁面載入完成之後呼叫 */
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
/* error - 頁面載入失敗時呼叫 */
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;
/* 其他 - 處理伺服器重定向Redirect */
- (void)webView:(WKWebView *)webView 
        didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
複製程式碼

我們看看WKUIDelegate的幾個代理方法,雖然不是必須實現的,但是如果我們的頁面中有呼叫了JS的alertconfirmprompt方法,我們應該實現下面這幾個代理方法,然後在這裡呼叫iOS的彈出窗,因為使用WKWebView後,HTML中的alertconfirmprompt方法呼叫是不會再彈出視窗了 ######下面列出WKUIDelegate的常用代理方法:

/* 輸入框,頁面中有呼叫JS的 prompt 方法就會呼叫該方法 */
- (void)webView:(WKWebView *)webView 
        runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt 
                                  defaultText:(nullable NSString *)defaultText 
                             initiatedByFrame:(WKFrameInfo *)frame 
                            completionHandler:(void (^)(NSString *result))completionHandler;
/* 確認框,頁面中有呼叫JS的 confirm 方法就會呼叫該方法 */
- (void)webView:(WKWebView *)webView 
        runJavaScriptConfirmPanelWithMessage:(NSString *)message 
                            initiatedByFrame:(WKFrameInfo *)frame 
                           completionHandler:(void (^)(BOOL result))completionHandler;
/* 警告框,頁面中有呼叫JS的 alert 方法就會呼叫該方法 */
- (void)webView:(WKWebView *)webView 
        runJavaScriptAlertPanelWithMessage:(NSString *)message 
                          initiatedByFrame:(WKFrameInfo *)frame 
                         completionHandler:(void (^)(void))completionHandler;
複製程式碼

WKWebView還有更多功能,比如和JavaScript互動等,但本人還不太理解,就不寫出來忽悠人了。

#####各位看官,如果喜歡我的文章,就點選關注我吧,如果有問題隨時可以在評論區講出來,O(∩_∩)O哈!

相關文章