標籤:效果 cal sel web 注入 use path 屬性 mac
代碼地址如下:
http://www.demodashi.com/demo/12754.html
JS-OC-Swift
JS和OC/Swift相互調用,主要總結了JS和OC互動的三種方式
1.使用UIWebView,利用JavaScriptCore實現
2.使用WKWebView,利用WKScriptMessageHandler實現
3.使用第三方架構WebViewJavascriptBridge實現
部分
JavaScriptCore
JavaScriptCore介紹
JavaScriptCore架構是基於webkit中以C/C++實現的JavaScriptCore的一個封裝,該架構讓Objective-C和JavaScript代碼直接的互動變得更加的簡單方便,主要由下面幾個類組成。
1.JSContext
JS執行的環境,同時也通過JSVirtualMachine管理著所有對象的生命週期,每個JSValue都和JSContext相關聯並且強引用context。可以通過[webView valueForKeyPath:@”documentView.webView.mainFrame.javaScriptContext”]來從webview上擷取相應的JSContext。
2.JSValue
JS對象在JSVirtualMachine中的一個強引用,其實就是Hybird對象。我們對JS的操作都是通過它。並且每個JSValue都是強引用一個context。同時,OC和JS對象之間的轉換也是通過它。
3.JSManagedValue
JS和OC對象的記憶體管理輔助對象。由於JS記憶體管理是記憶體回收,並且JS中的對象都是強引用,而OC是引用計數。如果雙方相互引用,勢必會造成循環參考,而導致記憶體泄露。我們可以用JSManagedValue儲存JSValue來避免。
4.JSVirtualMachine
JS啟動並執行虛擬機器,有獨立的堆空間和記憶體回收機制。
5.JSExport
一個協議,如果JS對象想直接調用OC對象裡面的方法和屬性,那麼這個OC對象只要實現這個JSExport協議就可以了。
在Swift中擷取JS的context
context = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as? JSContext
注入JS需要的對象,對象命名與html中使用的保持一致.self
是遵守了JSExport協議,也可是其他遵守協議的對象。
context?.setObject(self, forKeyedSubscript: "OC" as NSCopying & NSObjectProtocol)
JS調用Swift的方法,在Swift中實現協議
@objc protocol JSDelegate :JSExport { //包含參數的func,需要注意參數名對函數名稱的影響 func showMessageToYou(_ message:String) /* 對應html中“showAAndB”,此方法包含兩個參數,需要在參數前加“_” func showA(_ aString: String, andB: String) func showAAndB(_ aString:String,_ bStr:String) 以上兩個方法等同 */ func showAAndB(_ aString:String,_ bStr:String) func doActionCallBack()}
Swift調用JS的方法
let jsStr = String(format:"callback(‘%@‘)",(textField?.text)!)self.context?.evaluateScript(jsStr)
OC中可使用block和實現JSExport協議兩種方式實現,代碼實現:
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];self.context = context;//注入JS需要的“OC”對象,該對象與html中的保持一致即可self.context[@"OC"] = self;
WKScriptMessageHandler
初始化WKWebView後,添加供js調用oc/Swift的橋樑,這裡的name對應WKScriptMessage中的name
webView.configuration.userContentController.add(_ scriptMessageHandler: WKScriptMessageHandler, name: String)
遵守協議WKScriptMessageHandler,實現以下方法,可實現JS把訊息發送給OC/Swift。
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
OC/Swift調用JS
let jsStr = String(format:"callback(‘%@‘)",(textField?.text)!)self.webView.evaluateJavaScript(jsStr as String, completionHandler: { (result:Any?, error:Error?) in print("error:",error as Any) })
WebViewJavascriptBridge
WebViewJavascriptBridge是一個Objective-C與JavaScript進行訊息互連的第三方庫,可以很方便的實現OC和Javascript互調的功能。WebViewJavascriptBridge實現互調的過程也容易理解,就是在OC環境和Javascript環境各自儲存一個相互調用的bridge對象,每一個調用之間都有id和callbackid來找到兩個環境對應的處理。從Github上下載源碼之後,可以看到核心類主要包含如下幾個:
WebViewJavascriptBridge_JS:Javascript環境的Bridge初始化和處理。負責接收OC發給Javascript的訊息,並且把Javascript環境的訊息發送給OC。
WKWebViewJavascriptBridge/WebViewJavascriptBridge:主要負責OC環境的訊息處理,並且把OC環境的訊息發送給Javascript環境。
WebViewJavascriptBridgeBase:主要實現了OC環境的Bridge初始化和處理。
初始化WKWebViewJavascriptBridge
self.webViewBridge = [WKWebViewJavascriptBridge bridgeForWebView:self.webView];[self.webViewBridge setWebViewDelegate:self];
JS調用OC需要註冊事件
[self.webViewBridge registerHandler:@"handlerName" handler:^(id data, WVJBResponseCallback responseCallback) { //code}];
OC調用JS
[self.webViewBridge callHandler:@"handlerName" data:@[textField.text] responseCallback:^(id responseData) { NSLog(@"%@",responseData); }];
html中需要放置以下代碼
/*這段代碼是固定的,必須要放到js中*/function setupWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; var WVJBIframe = document.createElement(‘iframe‘); WVJBIframe.style.display = ‘none‘; WVJBIframe.src = ‘wvjbscheme://__BRIDGE_LOADED__‘; document.documentElement.appendChild(WVJBIframe); setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)}/*與OC互動的所有JS方法都要放在此處註冊,才能調用通過JS調用OC或者讓OC調用這裡的JS*/setupWebViewJavascriptBridge(function(bridge) { bridge.registerHandler(‘callback‘, function(data, responseCallback) { callback(data); responseCallback(‘js執行過了‘+data); })})
項目結構
JS與原生OC/Swift相互調用總結
代碼地址如下:
http://www.demodashi.com/demo/12754.html
註:本文著作權歸作者,由demo大師代發,拒絕轉載,轉載需要作者授權
JS與原生OC/Swift相互調用總結