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

昨天寫的這篇文章,今天就被推薦到首頁,上一篇博文也被微信iOS開發(fā)公眾號轉發(fā),感謝大家的支持,以后會一直分享優(yōu)質的原創(chuàng)內容,下一篇大家想看什么,下周給大家整理更新,歡迎大家評論或者私信我,共同進步.并且昨晚有人問我UIWebView的內存優(yōu)化,今天緊急整理了一下,博文傳送門:UIWebview的內存優(yōu)化方法

微信的小應用今天內測了,所以突發(fā)奇想,給大家整理一下JS與OC交互的三種方法.
16號我的iPhone7黑色也拿到手了,文章最后放圖鎮(zhèn)樓??

其實一直想給大家整理一下JS與OC的交互,但是沒有合適的機會,今天借著微信小應用的發(fā)布,以及以后H5必定越來越流行,所以給大家整理一下.

交互方式有三種:

  • 1.UIWebviewDelegate
  • 2.JavaScriptCore
  • 3.WebViewJavascriptBridge
    按照排序給大家介紹一下,我推薦前兩種方法,第三種需要依賴第三方框架,并且不一定能攔截成功,所以著重介紹前兩種,第三種知道怎么操作就行了

1.UIWebviewDelegate

第一種也是最簡單的一種,我在實際項目中就用的這個方法,根據UIWebviewDelegate的代理方法進行攔截

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
D92374E1-5043-44A8-A187-C8DA1794A71B.png

點擊新聞按鈕,根據shouldStartLoadWithRequest這個方法,打印出返回的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這個字符串,如果有進入if判斷,進行攔截,如果沒有,則return YES,放行;
    NSRange newRange = [[requestStr lowercaseString] rangeOfString:@"news"];
    if (newRange.length > 0) {
       //進行你需要的操作
        return NO;
    }
    return YES;
}

2.JavaScriptCore

這個是iOS7之后蘋果推出的一個JS于OC交互的一個框架,極大的方便了我們對js的操作

相關的幾個類
/*
JS執(zhí)行的環(huán)境,同時也通過JSVirtualMachine管理著所有對象的生命周期,每個JSValue都和JSContext相關聯并且強引用context。
*/
#import "JSContext.h"
/*
JS對象在JSVirtualMachine中的一個強引用,其實就是Hybird對象。我們對JS的操作都是通過它。并且每個JSValue都是強引用一個context。同時,OC和JS對象之間的轉換也是通過它
*/
#import "JSValue.h"
/*
JS和OC對象的內存管理輔助對象。由于JS內存管理是垃圾回收,并且JS中的對象都是強引用,而OC是引用計數。如果雙方相互引用,勢必會造成循環(huán)引用,而導致內存泄露。我們可以用JSManagedValue保存JSValue來避免。
*/
#import "JSManagedValue.h"
/*
JS運行的虛擬機,有獨立的堆空間和垃圾回收機制。
*/
#import "JSVirtualMachine.h"
/*
一個協議,如果JS對象想直接調用OC對象里面的方法和屬性,那么這個OC對象只要實現這個JSExport協議就可以了。
*/
#import "JSExport.h"

接下來就是如何去通過js來調用oc的方法了

//首先你要在本地的html文件里注冊一個按鈕,按鈕的打擊名字jsButton
<!DOCTYPE HTML>
<html lang="zh-CN">
  <body>
    <p>JavaScriptCore測試頁面</p>

    <body>
    <button onclick="jsButton()">JS按鈕</button>
  </body>
 </html>
//然后在加載完成的方法里通過JSContext來獲取相應操作的key值.key值是html文件里點擊方法的名字,并且調用你需要的操作
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    context[@"jsButton"] = ^{
        //在這里調用你需要的操作
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"點擊了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這個第三方庫,把js和oc之間搭建一個橋,來實現相互通信,這個是我最不推薦的一種方法,因為他需要依賴第三方庫來實現,通過互相注冊方法,增加代碼量并且并不是每次方法都能注冊上,有一定的失敗幾率,由于不推薦,所以就安排在最后,不做太詳細的解釋

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注冊js要調用Native

//handlerName:需要調用js的名字
//handler:需要oc進行的操作
- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler {
[_bridge registerHandler:@"scanClick" handler:^(id data, WVJBResponseCallback responseCallback) {
        //需要進行的操作
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"點擊了按鈕" 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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容