UIWebView和WKWebView比較

原先有些程式是使用UIWebView去開發,但是自iOS 8.0之後蘋果推薦使用WKWebView去取代舊有的元件,因此為了理解WKWebView與舊有的UIWebView相比有何進步之處,以及如何將UIWebView替換成WKWebView而去做了些整理。

WKWebView的優勢

  1. WKWebView適用於iOS和OS X。之前iOS是使用UIWebView而OS X是使用WebView,現在就可以都用WKWebView。
  2. WKWebView使用了Multi-process Architecture。WKWebView執行程序獨立於App之外,系統會統一管理以增進效能也更省電。建立WKWebView物件會分配個Web content processs,建立越多就會用越多Web content process,不過這會有個限制,過多的WKWebView會共享同個Web content process,因此當Web內容包含了許多JavaScript物件或複雜的動畫效果,APP依然可以持續地保持回應,也就是說如果WKWebView使用了過多的記憶體,他並不會Crash本身的App,只不過畫面會變成一片空白。
  3. WKWebView支援60fps的畫面滾動更新。藉由hardware acceleration和Core Animation達成。
  4. 使用Nitro JavaScript引擎。WKWebView採用了跟Safari一樣的JavaScript引擎大大地提升了效能。
  5. 內建手勢支援。返回上一頁和放大縮小手勢。
  6. App和Web page的溝通更方便。WKWebView新增了WKScriptMessageHandler協定,可以讓Objective-C或Swift透過監聽的方式,直接得到執行JavaScript的回應。

從UIWebView到WKWebView

WKWebView的方法與UIWebView相比而言是分的更多更細了,基本上UIWebView可以做到的功能WKWebView也可以做到,另外還增加了些新的功能。

Protocols

UIWebView WKWebView
var delegate: UIWebViewDelegate? var navigationDelegate: WKNavigationDelegate?
var uiDelegate: WKUIDelegate?

以Web頁面導覽功能來說,從UIWebView換到WKWebView只要把delegate換成navigationDelegate就可以滿足大部份的需求,不過如果有彈出視窗的介面需求就會需要用到uiDelegate。

Loading Content

UIWebView WKWebView
func loadRequest(URLRequest) func load(URLRequest) -> WKNavigation?
func loadHTMLString(String, baseURL: URL?) func loadHTMLString(String, baseURL: URL?) -> WKNavigation?
func load(Data, mimeType: String, textEncodingName: String, baseURL: URL) func load(Data, mimeType: String, characterEncodingName: String, baseURL: URL) -> WKNavigation?
func loadFileURL(URL, allowingReadAccessTo: URL) -> WKNavigation?

功能基本上也差不多,有一個比較要注意的地方是在iOS 8的版本WKWebView無法從main bundle直接讀取web的資源,直到iOS 9以上才解決了這個問題。

JavaScript Communication

UIWebView WKWebView
func stringByEvaluatingJavaScript(from script: String) -> String? func evaluateJavaScript(_ javaScriptString: String, completionHandler: ((Any?, Error?) -> Void)? = nil)

UIWebView執行JavaScript的方法為同步任務,而WKWebView則是非同步任務,因此使用UIWebView的方法可能會造成App有停頓的感覺,這裡WKWebView是比較適當的。

WKWebView還新增了兩種和JavaScript溝通的模式:

  1. 透過WKUserScript寫入JavaScript。透過WKWebView的設定,可以決定何時寫入JavaScript的Source以及寫入的位置,相比原來的方法有更多的彈性。

    let jsSource = "document.getElementsByTagName(\"h3\").style.fontSize = \"17px\""
    // 決定寫入JavaScript的方式
    let userScript = WKUserScript(source: source, injectionTime: .AtDocumentEnd, forMainFrameOnly: true)
    webView.configuration.userContentController.addUserScript(userScript)
    
  2. 使用WKScriptMessageHandler接收JavaScript執行結果。註冊一個message handler方法,就可以在Web呼叫這個方法時,通知App端這個方法被執行了,也可以藉此傳遞參數讓App得到Web內容的狀態。

    一開始要先註冊一個message handler:

    webView.configuration.userContentController.add(self, name: "callBack")
    

    在JavaScript的方法中去呼叫這個message handler加上傳遞參數:

    window.webkit.messageHandlers.callBack.postMessage("Hello");
    

    最後在App端去接收JavaScript回傳的結果:

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        guard let body: String = message.body as? String else { return }
        // 可以顯示出"Hello"的字串
        print(body)
    }
    

來源:

results matching ""

    No results matching ""