zoukankan      html  css  js  c++  java
  • WKWebView与JS交互,UIWebView+JavascriptCore和JS交互

    最近一直在做有关Swift和JavaScript交互的程序,所以有关UIWebView和WKWebView在使用上的差别在此总结下:

    UIWebView:

    (1)创建

    var webView: UIWebView!
    self.webView = UIWebView.init(frame: CGRect.init(x: 0, y: 0,  kScreenWidth, height: kScreenHeight))
    self.view.addSubview(self.webView!)
    self.webView.delegate = self

    (2)请求

    let url = ""
    let request = NSURLRequest(URL: NSURL(string: url)!)
    self.webView.loadRequest(request)

    (3)常用代理

    UIWebViewDelegate
    
    func webViewDidStartLoad(webView: UIWebView) {
    }
    func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
    }
    func webViewDidFinishLoad(webView: UIWebView) {
    }

     UIWebView最屌的当然还是结合传说中的JavaScriptCore的Hybrid方式了

    (4)在UIWebView中注入(执行)JS (注意要在webViewDidFinishLoad回调,也就是加载完后才能执行

    //第一种方法,直接webview执行(应该是封装了下面的方法二)
    let resultStr="1234"
    self.webView.stringByEvaluatingJavaScriptFromString("theFunc('"+resultStr+"');")! as String
    
    //第二种,使用kvc来取得mainframe的context,然后执行
    let context = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
    context.evaluateScript(theScript)

    (5)在UIWebView中监听JS的函数,这种方式可以通过原生return来call back,不过return是一种同步的call back。不是非常好。

    let context = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
    
    //假如JS传给原生一个JSON的字符串
    let accountSerial: @convention(block) String -> () = { _ in
        let value = JSContext.currentArguments().first
        let data = value?.toString().dataUsingEncoding(NSUTF8StringEncoding)
        let accountInfoDic = try? NSJSONSerialization.JSONObjectWithData(data!, options:[]) as! NSDictionary
    }
    context.setObject(unsafeBitCast(accountSerial, AnyObject.self), forKeyedSubscript: "saveAccountInfo")
    
    //假如需要原生return一个JSON的字符串
    let cookiesSerial : @convention(block) () -> String = {
        let cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookiesForURL((webView.request?.URL)!)
        let header=NSHTTPCookie.requestHeaderFieldsWithCookies(cookies!) as NSDictionary
        if(header.objectForKey("Cookie") != nil) {
             return  cookies.toJsonString()
        }
    }

     (6)另外一种奇葩的通过URL拦截的方式,让JS调用原生

    http://www.cnblogs.com/rayshen/p/4560728.html

    WKWebView:

    (1)创建,需要import的框架和继承的协议

    //需要导入
    import WebKit
    
    class MXWebDemoController:UIViewController,WKNavigationDelegate,WKUIDelegate,WKScriptMessageHandler{}
    
    private var webView:WKWebView!
    private var progressView:UIProgressView!
    
    //进度条
    progressView = UIProgressView(progressViewStyle: UIProgressViewStyle.Default)
    progressView.frame = CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, 22)
    progressView.tintColor = UIColor.blueColor()
    self.view.addSubview(progressView)
    //初始化
    let conf = WKWebViewConfiguration()
    webView = WKWebView(frame: CGRectMake(0,0,kScreenWidth,kScreenHeight), configuration: conf)
    self.view.insertSubview(webView, belowSubview: progressView)

    (2)请求

    let request = NSURLRequest(URL: NSURL(string:baseUrl)!, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 10)
    self.webView.loadRequest(request)

    (3)常用代理

    //webview加载完,重置进度条
    func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
            progressView.setProgress(0.0, animated: false)
        }
    
    //kvo监听    
    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
            if keyPath == "estimatedProgress" {
                progressView.hidden = webView.estimatedProgress == 1
                progressView.setProgress(Float(webView.estimatedProgress), animated: true)
            }
        }
        
        //和JS消息交互
        // MARK: -  WKScriptMessageHandler
        func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
            if(message.name == "mxBack"){
                self.navigationController?.popViewControllerAnimated(true)
            }
        }

    (4)JS注入,最基本的就是evaluateJavaScript函数,在页面加载完后去执行。再而,WKWebView新增了JS注入的接口。

    //方法1
    let jsStr = ""
    webView.evaluateJavaScript(jsStr),completionHandler: { (object, error) in
         if(error != nil){
            print(error)
         }
    })   
    
    //方法2
    let script = WKUserScript(source:self.scriptStr,injectionTime: .AtDocumentStart,forMainFrameOnly: true)

    (5)接受来自JS的消息

    //1
    conf.userContentController.addScriptMessageHandler(self, name:"mxBack")
    
    
    
    //2
    func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
            weak var weakself = self
            if(message.name == "mxBack"){
                self.hasGetResult = true
                self.gotoBack()
            }
    }

    有关WKWebView,有个缺点,就是和JS之间没有同步的函数(依靠return来回传的方式)。

    之前大部分iOS项目都是使用UIWebView,现在iOS8后Webkit良好的性能取代了UIWebView,但它的异步对很多旧的Web工程都有点影响。

    别人的Demo:

    https://github.com/CoderJackyHuang/WKWebViewTestDemo

    下周有空我会写个更好的,更详细的介绍JS和原生之间的交互。

  • 相关阅读:
    HDU 6182 A Math Problem 水题
    HDU 6186 CS Course 位运算 思维
    HDU 6188 Duizi and Shunzi 贪心 思维
    HDU 2824 The Euler function 欧拉函数
    HDU 3037 Saving Beans 多重集合的结合 lucas定理
    HDU 3923 Invoker Polya定理
    FZU 2282 Wand 组合数学 错排公式
    HDU 1452 Happy 2004 数论
    HDU 5778 abs 数论
    欧拉回路【判断连通+度数为偶】
  • 原文地址:https://www.cnblogs.com/rayshen/p/5343103.html
Copyright © 2011-2022 走看看