UIWebView中Objective-C和JavaScript通信

JS和OC的交互,使用到JavaScriptCore這個框架,用到的類和協議有JSExportJSContext

網頁很簡單,只有一個button按鈕,button按鈕的事件點擊主要執行了wst.duobao('123');wst是自定義的一個普通JS對象,在OC中需要使用到wst捕獲對應的js方法調用。
網頁html代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>html5page-oc</title>

    <script>
        wst = new Object();
        wst.duobao = function () {}

        function btn1Click() {
            wst.duobao('123');
            alert("after call");
        }
    </script>

</head>
<body>

<input type="button" value="button c" onclick="btn1Click()">

</body>
</html>

OC處理JS的事件回調,主要步驟

  1. 定義JSContext的對象jsContext
  2. 在WebView的代理方法webViewDidFinishLoad:中調用[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]獲取到JSContext的對象。
  3. 調用_jsContext[@"wst"] = self;註冊JS中的對象wst派發的方法的處理模塊,這裏是把處理wst模塊的代理設置爲當前類,實際中如果有多個模塊可以使用一個自定義的實現JSExport來單獨處理JS的邏輯,本例中有實現了JSExport協議的自定義協議JavaScriptObjectiveCDelegate,具體看第4點
  4. 自定義繼承JSExport協議JavaScriptObjectiveCDelegate,這邊定義JS和OC交互的接口。
  5. 實現JavaScriptObjectiveCDelegate,重寫對應的方法處理JS的回調,注意JS回調的方法是在子線程執行的,如果涉及到UI操作,需要派發到主線程中處理。

OC調用JS方法

調用JSContext的方法evaluateScript,參數爲JS代碼即可

 [_jsContext evaluateScript:@"alert('oc call js')"];

完整的代碼如下:


// 自定義繼承`JSExport`協議,這邊定義JS和OC交互的接口
@protocol JavaScriptObjectiveCDelegate <JSExport>

- (void)duobao(NSString*)params;

@end

@interface YTTWebViewController ()<UIWebViewDelegate, UIScrollViewDelegate, JavaScriptObjectiveCDelegate>

@property (nonatomic, strong) UIWebView *webView;
@property (nonatomic, strong, readonly) JSContext *jsContext;

@end

// ...

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    if (_jsContext == nil) {
        // 1.從WebView中獲取到JSContext對象
        _jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        
        // 2. 關聯打印異常
        _jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
            context.exception = exceptionValue;
            NSLog(@"異常信息:%@", exceptionValue);
        };
        _jsContext[@"wst"] = self;
    }
    
    // OC調用JS
    [_jsContext evaluateScript:@"alert('oc call js')"];
}

#pragma mark - JavaScriptObjectiveCDelegate
-(void)duobao {
    // JS調用OC是在子線程
    NSLog(@"current thread = %@", [NSThread currentThread]);
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"js call oc");
    });
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章