史上最全的UIWebview的JS與OC交互

昨天寫的這篇文章,今天就被推薦到首頁,上一篇博文也被微信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{
D92374E1-5043-44A8-A187-C8DA1794A71B.png

點(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:^{
            
        }];
    }];

demo地址

和我之前的6s比起來就是,比好更好,套用蘋果式的廣告語


BA9A668E-2018-402F-A8A7-D135DC2F02DB.JPG
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容