iOS必须SwiftUIWebView和JS交互程序员

 webView中JavaScript交互(swift)

2017-01-24  本文已影响323人  轻云_

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前端开发人员来定义,让另外两端去做适配,例如:

Snip0.png

模型注入完毕后就可以使用JS中定义的方法调用我们原生的代码了

上一篇下一篇

猜你喜欢

热点阅读