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和原生之间的交互。

  • 相关阅读:
    您还在用下一步下一步的方式安装SQLSERVER和SQLSERVER补丁吗?
    SQLSERVER误删除了Windows登录用户验证方式使用Windows身份验证的解决方法
    批量解密SQLSERVER数据库中的各种对象的工具dbForge SQL Decryptor
    SQLSERVER将数据移到另一个文件组之后清空文件组并删除文件组
    SQLSERVER群集故障转移笔记
    兼容,原来在这里就已经開始--------Day34
    Objective-C的对象模型和runtime机制
    CF B. Kolya and Tandem Repeat
    循环队列的实现
    LintCode 子树
  • 原文地址:https://www.cnblogs.com/rayshen/p/5343103.html
Copyright © 2011-2022 走看看