iOS7之后加入的JavaScriptCore框架使JS的交互變得更加簡單方便,JSVirtualMachine為JavaScript的運(yùn)行提供了底層資源,JSContext就為其提供著運(yùn)行環(huán)境,而JSValue是JavaScript和Object-C之間互換的橋梁,它提供了多種方法可以方便地實(shí)現(xiàn)JavaScript數(shù)據(jù)類型與Objective-C之間的相互轉(zhuǎn)換
swift直接執(zhí)行JS代碼沒什么好介紹的,說一下JS方法中調(diào)用swift代碼
import JavaScriptCore 導(dǎo)入框架
//創(chuàng)建web視圖并加載鏈接
let webView = UIWebView(frame: CGRectMake(0,64,WIDTH,HEIGHT-64-49))
let URL = NSURL(string:adSourceUrl)
let request = NSURLRequest(URL: URL!)
webView.loadRequest(request)
webView.delegate = self
//尺寸適應(yīng)
webView.scalesPageToFit = true
self.view.addSubview(webView)
在Swift中通過JSContext注入模型,然后調(diào)用模型的方法
// 定義協(xié)議SwiftJavaScriptDelegate 該協(xié)議必須遵守JSExport協(xié)議
@objc protocol SwiftJavaScriptDelegate: JSExport {
func click0(btnId: String)
}
// 定義一個(gè)模型 該模型實(shí)現(xiàn)SwiftJavaScriptDelegate協(xié)議
@objc class SwiftJavaScriptModel: NSObject, SwiftJavaScriptDelegate {
weak var controller: UIViewController?
weak var jsContext: JSContext?
//內(nèi)部為自定義要實(shí)現(xiàn)的方法(比如點(diǎn)擊html按鈕調(diào)用swift方法)
dynamic func click0(btnId: String) {
print("___這是點(diǎn)擊按鈕的ID_____\(btnId)___________")
let sb = UIStoryboard(name: "Activity", bundle: nil)
let vc: ActivityDeatilViewController = sb.instantiateViewControllerWithIdentifier("ActivityDeatilViewController") as!ActivityDeatilViewController
vc.hidesBottomBarWhenPushed = true
vc.hudNum = 1
if btnId != "null" {
vc.id = btnId
}
self.controller?.navigationController?.pushViewController(vc, animated: true)
}
}
在webViewDidFinishLoad代理中將我們定義的模型注入到網(wǎng)頁中,暴露給JS
dynamic func webViewDidFinishLoad(webView: UIWebView) {
hud.hideAnimated(true)
print("__________網(wǎng)頁加載完成___________")
self.jsContext = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
let model = SwiftJavaScriptModel()
model.controller = self
model.jsContext = self.jsContext
// 這一步是將SwiftJavaScriptModel模型注入到JS中,在JS就可以通過button調(diào)用我們暴露的方法了。
// self.jsContext.setObject(model, forKeyedSubscript: "button" as (NSCopying & NSObjectProtocol)!)
//這里注意要和前端定義的一致
self.jsContext.setObject(model, forKeyedSubscript: "button")
// 注冊到本地的Html頁面中
// let url = Bundle.main.url(forResource: "demo", withExtension: "html")
// self.jsContext.evaluateScript(try? String(contentsOf: url!, encoding: String.Encoding.utf8))
// 注冊到網(wǎng)絡(luò)Html頁面
let url = NSURL(string: adSourceUrl)
// let curUrl = self.webView.request?.URL?.absoluteString //WebView當(dāng)前訪問頁面的鏈接 可動態(tài)注冊
self.jsContext.evaluateScript(try? String(contentsOfURL: url!, encoding: NSUTF8StringEncoding))
self.jsContext.exceptionHandler = { (context, exception) in
print("exception:", exception)
}
}
其中傳值或方法命名最好web前端開發(fā)人員來定義,讓另外兩端去做適配,例如:

Snip0.png
模型注入完畢后就可以使用JS中定義的方法調(diào)用我們原生的代碼了