JS和OC的交互,使用到JavaScriptCore
這個框架,用到的類和協議有JSExport
、JSContext
網頁很簡單,只有一個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的事件回調,主要步驟
- 定義
JSContext
的對象jsContext
。 - 在WebView的代理方法
webViewDidFinishLoad:
中調用[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]
獲取到JSContext
的對象。 - 調用
_jsContext[@"wst"] = self;
註冊JS中的對象wst
派發的方法的處理模塊,這裏是把處理wst
模塊的代理設置爲當前類,實際中如果有多個模塊可以使用一個自定義的實現JSExport
來單獨處理JS的邏輯,本例中有實現了JSExport
協議的自定義協議JavaScriptObjectiveCDelegate
,具體看第4點
。 - 自定義繼承
JSExport
協議JavaScriptObjectiveCDelegate
,這邊定義JS和OC交互的接口。 - 實現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");
});
}