昨天寫的這篇文章,今天就被推薦到首頁,上一篇博文也被微信
iOS開發(fā)公眾號(hào)轉(zhuǎn)發(fā),感謝大家的支持,以后會(huì)一直分享優(yōu)質(zhì)的原創(chuàng)內(nèi)容,下一篇大家想看什么,下周給大家整理更新,歡迎大家評(píng)論或者私信我,共同進(jìn)步.并且昨晚有人問我UIWebView的內(nèi)存優(yōu)化,今天緊急整理了一下,博文傳送門:UIWebview的內(nèi)存優(yōu)化方法
微信的小應(yīng)用今天內(nèi)測(cè)了,所以突發(fā)奇想,給大家整理一下JS與OC交互的三種方法.
16號(hào)我的iPhone7黑色也拿到手了,文章最后放圖鎮(zhèn)樓??
其實(shí)一直想給大家整理一下JS與OC的交互,但是沒有合適的機(jī)會(huì),今天借著微信小應(yīng)用的發(fā)布,以及以后H5必定越來越流行,所以給大家整理一下.
交互方式有三種:
- 1.UIWebviewDelegate
- 2.JavaScriptCore
- 3.WebViewJavascriptBridge
按照排序給大家介紹一下,我推薦前兩種方法,第三種需要依賴第三方框架,并且不一定能攔截成功,所以著重介紹前兩種,第三種知道怎么操作就行了
1.UIWebviewDelegate
第一種也是最簡(jiǎn)單的一種,我在實(shí)際項(xiàng)目中就用的這個(gè)方法,根據(jù)UIWebviewDelegate的代理方法進(jìn)行攔截
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{

點(diǎn)擊新聞按鈕,根據(jù)shouldStartLoadWithRequest這個(gè)方法,打印出返回的url地址為
QQ20160922-0.png
QQ20160922-1.png
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSString *requestStr = [request.URL absoluteString];
NSLog(@"%@",requestStr);
//判斷返回的url是否包含news這個(gè)字符串,如果有進(jìn)入if判斷,進(jìn)行攔截,如果沒有,則return YES,放行;
NSRange newRange = [[requestStr lowercaseString] rangeOfString:@"news"];
if (newRange.length > 0) {
//進(jìn)行你需要的操作
return NO;
}
return YES;
}
2.JavaScriptCore
這個(gè)是iOS7之后蘋果推出的一個(gè)JS于OC交互的一個(gè)框架,極大的方便了我們對(duì)js的操作
相關(guān)的幾個(gè)類
/*
JS執(zhí)行的環(huán)境,同時(shí)也通過JSVirtualMachine管理著所有對(duì)象的生命周期,每個(gè)JSValue都和JSContext相關(guān)聯(lián)并且強(qiáng)引用context。
*/
#import "JSContext.h"
/*
JS對(duì)象在JSVirtualMachine中的一個(gè)強(qiáng)引用,其實(shí)就是Hybird對(duì)象。我們對(duì)JS的操作都是通過它。并且每個(gè)JSValue都是強(qiáng)引用一個(gè)context。同時(shí),OC和JS對(duì)象之間的轉(zhuǎn)換也是通過它
*/
#import "JSValue.h"
/*
JS和OC對(duì)象的內(nèi)存管理輔助對(duì)象。由于JS內(nèi)存管理是垃圾回收,并且JS中的對(duì)象都是強(qiáng)引用,而OC是引用計(jì)數(shù)。如果雙方相互引用,勢(shì)必會(huì)造成循環(huán)引用,而導(dǎo)致內(nèi)存泄露。我們可以用JSManagedValue保存JSValue來避免。
*/
#import "JSManagedValue.h"
/*
JS運(yùn)行的虛擬機(jī),有獨(dú)立的堆空間和垃圾回收機(jī)制。
*/
#import "JSVirtualMachine.h"
/*
一個(gè)協(xié)議,如果JS對(duì)象想直接調(diào)用OC對(duì)象里面的方法和屬性,那么這個(gè)OC對(duì)象只要實(shí)現(xiàn)這個(gè)JSExport協(xié)議就可以了。
*/
#import "JSExport.h"
接下來就是如何去通過js來調(diào)用oc的方法了
//首先你要在本地的html文件里注冊(cè)一個(gè)按鈕,按鈕的打擊名字jsButton
<!DOCTYPE HTML>
<html lang="zh-CN">
<body>
<p>JavaScriptCore測(cè)試頁面</p>
<body>
<button onclick="jsButton()">JS按鈕</button>
</body>
</html>
//然后在加載完成的方法里通過JSContext來獲取相應(yīng)操作的key值.key值是html文件里點(diǎn)擊方法的名字,并且調(diào)用你需要的操作
- (void)webViewDidFinishLoad:(UIWebView *)webView {
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
context[@"jsButton"] = ^{
//在這里調(diào)用你需要的操作
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"點(diǎn)擊了JS按鈕" message:@"" preferredStyle:(UIAlertControllerStyleAlert)];
UIAlertAction *sureAlertAction = [UIAlertAction actionWithTitle:@"OK" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {
}];
[alert addAction:sureAlertAction];
[self presentViewController:alert animated:YES completion:^{
}];
};
}
3.WebViewJavascriptBridge
第三種方法是通過WebViewJavascriptBridge這個(gè)第三方庫,把js和oc之間搭建一個(gè)橋,來實(shí)現(xiàn)相互通信,這個(gè)是我最不推薦的一種方法,因?yàn)樗枰蕾嚨谌綆靵韺?shí)現(xiàn),通過互相注冊(cè)方法,增加代碼量并且并不是每次方法都能注冊(cè)上,有一定的失敗幾率,由于不推薦,所以就安排在最后,不做太詳細(xì)的解釋
3.1創(chuàng)建webview
UIWebView* webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:webView];
NSString *path = [[NSBundle mainBundle] pathForResource:@"JSBridge" ofType:@"html"];
NSURL *baseURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
NSString *htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[webView loadHTMLString:htmlString baseURL:baseURL];
[self.view addSubview:webView];
3.2創(chuàng)建WebViewJavascriptBridge
[WebViewJavascriptBridge enableLogging];
_bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
[_bridge setWebViewDelegate:self];
3.3注冊(cè)js要調(diào)用Native
//handlerName:需要調(diào)用js的名字
//handler:需要oc進(jìn)行的操作
- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler {
[_bridge registerHandler:@"scanClick" handler:^(id data, WVJBResponseCallback responseCallback) {
//需要進(jìn)行的操作
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"點(diǎn)擊了按鈕" message:@"" preferredStyle:(UIAlertControllerStyleAlert)];
UIAlertAction *sureAlertAction = [UIAlertAction actionWithTitle:@"OK" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {
}];
[alert addAction:sureAlertAction];
[self presentViewController:alert animated:YES completion:^{
}];
}];
和我之前的6s比起來就是,比好更好,套用蘋果式的廣告語

