UIWebView
JS調(diào)用OC
1.重定向URL攔截
每次打開(kāi)一個(gè)鏈接之前,都會(huì)觸發(fā)下面的代理方法
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
標(biāo)準(zhǔn)的URL包含scheme、host、port、path、query、fragment,通過(guò)判斷來(lái)獲取相應(yīng)的參數(shù)和執(zhí)行的方法
特點(diǎn):比較靈活,常用于頁(yè)面的跳轉(zhuǎn),但無(wú)法提供返回值,適用于單向傳參,無(wú)回調(diào)的情況
2.JavaScriptCore(iOS 7.0 +)
WebKit都有一個(gè)內(nèi)嵌的js環(huán)境,一般我們?cè)陧?yè)面加載完成之后,獲取js上下文
JavaScriptCore是JS到OC的映射,可以替換各種js方法成oc方法.
//獲取上下文
self.context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//設(shè)置OC的函數(shù)體
self.context[@“JSMethodName”] = ^() {
NSArray *args = [JSContext currentArguments];//獲取所有參數(shù)
//args中的元素是JSValue,需要轉(zhuǎn)成OC的對(duì)象
NSMutableArray *messages = [NSMutableArray array];
for (JSValue *obj in args) {
[messages addObject:[obj toObject]];
}
NSLog(@"js傳過(guò)來(lái)的參數(shù):\n%@", messages);
//do something .....
};
//通過(guò)JSExport,設(shè)置js的代理為遵循JSExport的實(shí)例,在協(xié)議中定義交互的方法,在JavaScript中通過(guò)指定代理對(duì)象名稱(比如下面:JavaScriptInterface),來(lái)調(diào)用協(xié)議中定義的方法,實(shí)現(xiàn)傳參或者獲取返回值到j(luò)s環(huán)境
self.context[@"JavaScriptInterface"] = self;
OC調(diào)用JS
1.UIWebView的stringByEvaluatingJavaScriptFromString:
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
可以看到返回值是NSString,參數(shù)script是js語(yǔ)法組成的字符串
- 通過(guò)UIWebview調(diào)用
- 無(wú)法捕獲異常,發(fā)生錯(cuò)誤返回nil,若無(wú)返回值,無(wú)法判斷調(diào)用是否成功
- 返回值是NSString,當(dāng)是其他類(lèi)型,則需要進(jìn)行解析.
- JavaScriptCore(iOS 7.0 +)
通過(guò)JSContext的evaluateScript:方法來(lái)獲取返回值。該方法得到的是一個(gè)JSValue對(duì)象,所以支持JavaScript的Array、Number、String、對(duì)象等數(shù)據(jù)類(lèi)型。
//獲取標(biāo)題
JSValue *value = [self.context evaluateScript:@"document.title"];
//設(shè)置捕獲異常回調(diào)
[self.context setExceptionHandler:^(JSContext *context, JSValue *exception){
NSLog(@"%@", exception);
}];
//執(zhí)行js的函數(shù)
[self.context evaluateScript:@“jsMethod()”];
WebViewJavascriptBridge的實(shí)現(xiàn)原理:
初始化將Webview的代理設(shè)置為自己,對(duì)當(dāng)前self持有一個(gè)引用
js調(diào)用OC通過(guò)代理方法攔截,OC調(diào)用js通過(guò)webview執(zhí)行evaluateScript:;將一個(gè)名為callback的function作為參數(shù),通過(guò)一些封裝,傳遞到OC(js->oc 傳遞參數(shù)和callbackId),然后在OC端執(zhí)行完畢,再通過(guò)block來(lái)回調(diào)callback(oc->js,傳遞返回值參數(shù)),實(shí)現(xiàn)異步獲取返回值