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, width: 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和原生之間的交互。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM