iOS7之后加入的JavaScriptCore框架使JS的交互变得更加简单方便,JSVirtualMachine为JavaScript的运行提供了底层资源,JSContext就为其提供着运行环境,而JSValue是JavaScript和Object-C之间互换的桥梁,它提供了多种方法可以方便地实现JavaScript数据类型与Objective-C之间的相互转换
swift直接执行JS代码没什么好介绍的,说一下JS方法中调用swift代码
import JavaScriptCore 导入框架
//创建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
//尺寸适应
webView.scalesPageToFit = true
self.view.addSubview(webView)
在Swift中通过JSContext注入模型,然后调用模型的方法
// 定义协议SwiftJavaScriptDelegate 该协议必须遵守JSExport协议
@objc protocol SwiftJavaScriptDelegate: JSExport {
func click0(btnId: String)
}
// 定义一个模型 该模型实现SwiftJavaScriptDelegate协议
@objc class SwiftJavaScriptModel: NSObject, SwiftJavaScriptDelegate {
weak var controller: UIViewController?
weak var jsContext: JSContext?
//内部为自定义要实现的方法(比如点击html按钮调用swift方法)
dynamic func click0(btnId: String) {
print("___这是点击按钮的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代理中将我们定义的模型注入到网页中,暴露给JS
dynamic func webViewDidFinishLoad(webView: UIWebView) {
hud.hideAnimated(true)
print("__________网页加载完成___________")
self.jsContext = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
let model = SwiftJavaScriptModel()
model.controller = self
model.jsContext = self.jsContext
// 这一步是将SwiftJavaScriptModel模型注入到JS中,在JS就可以通过button调用我们暴露的方法了。
// 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))
// 注册到网络Html页面
let url = NSURL(string: adSourceUrl)
// let curUrl = self.webView.request?.URL?.absoluteString //WebView当前访问页面的链接 可动态注册
self.jsContext.evaluateScript(try? String(contentsOfURL: url!, encoding: NSUTF8StringEncoding))
self.jsContext.exceptionHandler = { (context, exception) in
print("exception:", exception)
}
}
其中传值或方法命名最好web前端开发人员来定义,让另外两端去做适配,例如:
模型注入完毕后就可以使用JS中定义的方法调用我们原生的代码了