1. 程式人生 > >iOS開發與H5互動的整理總結

iOS開發與H5互動的整理總結

UIWebView delegate 協議方法

//UIWebView自帶了一個方法, 可以直接呼叫JS程式碼(轉化為string型別的js程式碼)
 - (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

 //例如修改id為‘html’標籤內部的text屬性
 [web stringByEvaluatingJavaScriptFromString:@"document.getElementById('html').innerText='修改內容'"];

 //也可以執行多行js程式碼
 [web stringByEvaluatingJavaScriptFromString:@"var div = document.getElementById('html'); div.innerText = '修改內容'"];

利用JavaScriptCore實現互動 

JavaScriptCore中類及協議:

JSContext:給JavaScript提供執行的上下文環境
 JSValue:JavaScript和Objective-C資料和方法的橋樑
 JSManagedValue:管理資料和方法的類
 JSVirtualMachine:處理執行緒相關,使用較少
 JSExport:這是一個協議,如果採用協議的方法互動,自己定義的協議必須遵守此協議

OC中提供了JavaScriptCore 這個庫,使得OC與js的互動變得更加方便。
 使用方法:
 1  加入JavaScriptCore 這個framework
 2  引入標頭檔案<JavaScriptCore/JavaScriptCore.h>
 3  在VC裡面加入一個JSContext屬性
    @property (strong, nonatomic) JSContext *context;
    JSContext是什麼那? 我們看一下api裡面的解釋

JSContext是一個JS的執行環境,所有的JS執行都發生在一個context裡面, 所有的JS value都繫結到context裡面 

具體使用如下:

//初始化context
 self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
 //OC呼叫JS
 //(1)例如html的script中一個方法
   function dolike(a,b,c){
   }
 //通過OC呼叫此方法
 NSString * method = @"dolike";
 JSValue * function = [self.context objectForKeyedSubscript:method];
 //這裡面的a,b,c就是OC呼叫JS的時候給JS傳的引數
 [function callWithArguments:@[a,b,c]];

 //JS呼叫OC
 //例如網頁中有個標籤,點選button的時候呼叫Jump方法, 此處3為傳入的引數
 <button onclick="jump('3')">點我</button>
 //當點選網頁中的button的時候,觸發jump方法, 在OC中用如下程式碼可以捕捉到jump方法, 並拿到JS給我傳的引數‘3’
 self.context[@"jump"] = ^(NSString * str){
 //此處 str 值為'3'(js呼叫OC時傳給OC的引數)
 };

WKWebView

說到WKWebView, 首先要說下WKWebView的優勢

1 更多的支援HTML5的特性 
2 官方宣稱的高達60fps的滾動重新整理率以及內建手勢 
3 將UIWebViewDelegate與UIWebView拆分成了14類與3個協議,以前很多不方便實現 的功能得以實現 
4 Safari相同的JavaScript引擎 
5 佔用更少的記憶體

類:
WKBackForwardList: 之前訪問過的 web 頁面的列表,可以通過後退和前進動作來訪問到。
WKBackForwardListItem: webview 中後退列表裡的某一個網頁。
WKFrameInfo: 包含一個網頁的佈局資訊。
WKNavigation: 包含一個網頁的載入進度資訊。
WKNavigationAction: 包含可能讓網頁導航變化的資訊,用於判斷是否做出導航變化。
WKNavigationResponse: 包含可能讓網頁導航變化的返回內容資訊,用於判斷是否做出導航變化。
WKPreferences: 概括一個 webview 的偏好設定。
WKProcessPool: 表示一個 web 內容載入池。
WKUserContentController: 提供使用 JavaScript post 資訊和注射 script 的方法。
WKScriptMessage: 包含網頁發出的資訊。
WKUserScript: 表示可以被網頁接受的使用者指令碼。
WKWebViewConfiguration: 初始化 webview 的設定。
WKWindowFeatures: 指定載入新網頁時的視窗屬性。

協議:
WKNavigationDelegate: 提供了追蹤主視窗網頁載入過程和判斷主視窗和子視窗是否進行頁面載入新頁面的相關方法。
WKScriptMessageHandler: 提供從網頁中收訊息的回撥方法。
WKUIDelegate: 提供用原生控制元件顯示網頁的方法回撥。

WKWebView的 UIDelegate 提供了三個協議方法, 可以讓前端很方便的攔截JS的alert, confirm, prompt方法。除此之外,OC,JS互調可以按照如下方法。

1 OC 呼叫JS

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;

//例如OC呼叫JS的方法 setName

   [webView evaluateJavaScript:@"setname('張三')" completionHandler:nil];

//此處 setname為JS定義的方法名, 內部 ‘張三’為傳給JS的引數。 如果setname方法需要傳入一個json或者array等非字元引數, 需要用format方法將其轉為string型別,在呼叫evaluate方法。例如

   NSString * para = [NSString stringWithFormat:@"setname('%@')",json];

JS呼叫OC

此時就要用到WKScriptMessageHandler了

//首先.m中加入屬性
 @property (nonatomic ,strong)WKUserContentController * userCC;


//1 遵循WKScriptMessageHandler協議
//2 初始化
   WKWebViewConfiguration * config = [[WKWebViewConfiguration alloc]init];

 self.wkWebViw = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];

 [self.wkWebViw loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.webPageUrl]]];

 [self.view addSubview:self.wkWebViw];

 self.userCC = config.userContentController;

 [self.userCC addScriptMessageHandler:self name:@"callOSX"];

 //此處相當於監聽了JS中callFunction這個方法

 [self.userCC addScriptMessageHandler:self name:@"callFunction"];

 //當JS發出callFunction這個方法指令的時候, WKScriptMessageHandler的協議方法中我們就會收到這個訊息

 #pragma mark  WKScriptMessageHandler delegate
 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
 {
//這個回撥裡面, message.name代表方法名(‘本例為 callFunction’), message.body代表JS給我們傳過來的引數

 }

//最後, VC銷燬的時候一定要把handler移除
-(void)dealloc
{
    [_userContentController removeScriptMessageHandlerForName:@"callFunction"];
}


//對應的JS程式碼

<button onclick="buttonClick('溫馨提示')">點我</button>

<script>
       function buttonClick(string){
       //JS呼叫OC, 格式如下
       //(window.webkit.messageHandlers.Method_Name.postMessage(parameterToOC))
              window.webkit.messageHandlers.callFunction.postMessage(string)
        }       
</script>