由於前陣子寫了個 iOS 的 app 是需要開啟網頁的,所以又接觸了 Webkit 相關的東東。由於 UIWebView 已經被列為古蹟,所以這次使用了 WKWebView。

基於這個原因,所以就利用 WKWebView 做了一個簡單的瀏覽器,只有最基本的瀏覽功能。

要使用 WKWebView,要先導入 Webkit framework。

import WebKit

在 view controller 內建立一個 WKWebView 物件,以及一個 UIView 作顯示用途。

@IBOutlet var webviewView: UIView!
var webview: WKWebView!

於 viewDidLoad 內進行初始化。

webview = WKWebView(frame: .zero)
webviewView.addSubview(webview)

載入網頁。

let tURL = URL("https://www.google.com")
webview.load(URLRequest(url: tURL))

剛開始時,是在 Storyboard 拖了一個 WKWebView 到 view controller 內,再於 code 內 load 一個網址,可是試了一陣子也只有一個白色的畫面。然後就找 Google 大神幫忙看看,大概是 constrains 的問題(但也可能是沒設定 ATS,沒仔細研究)。於是改了用另一個方法,先放一個 UIView 進去,再於 code 內把 WKWebView 放至該 UIView 內,然後設定 constrains,然後終於有了畫面。

webview = WKWebView(frame: .zero)
webviewView.addSubview(webview)

webview.translatesAutoresizingMaskIntoConstraints = false

let height = NSLayoutConstraint(item: webview, attribute: .height, relatedBy: .equal, toItem: webviewView, attribute: .height, multiplier: 1, constant: 0)

let width = NSLayoutConstraint(item: webview, attribute: .width, relatedBy: .equal, toItem: webviewView, attribute: .width, multiplier: 1, constant: 0)

let leftConstraint = NSLayoutConstraint(item: webview, attribute: .leftMargin, relatedBy: .equal, toItem: webviewView, attribute: .leftMargin, multiplier: 1, constant: 0)

let rightConstraint = NSLayoutConstraint(item: webview, attribute: .rightMargin, relatedBy: .equal, toItem: webviewView, attribute: .rightMargin, multiplier: 1, constant: 0)

let bottomContraint = NSLayoutConstraint(item: webview, attribute: .bottomMargin, relatedBy: .equal, toItem: webviewView, attribute: .bottomMargin, multiplier: 1, constant: 0)

webviewView.addConstraints([height, width, leftConstraint, rightConstraint, bottomContraint])

網頁讀取進度好像跟 UIWebView 也不一樣,要利用 KVO 才能有效利用。然後還要設定 ATS,才可以讓你的 app 能夠讀取使用 HTTP 的 URL,否則只能開啟 HTTPS 的網頁。

先加一個 observer

webview.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)

再加入以下 function 來處理

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "estimatedProgress" {
        progressBar.progress = Float(webview.estimatedProgress)
    }
}

利用 WKNavigationDelegate,可以於讀取網頁的不同階段進行不同的處理,例如被重新導向至新的網址時更新網址列的顯示。

public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!){
    print("Start provisional navigation")
    urlText.text = webview.url?.absoluteString
}

public func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!){
    print("Receive server redirect for provisional navigation")
    urlText.text = webview.url?.absoluteString
}

public func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error){
    print("Fail provisional navigation")
}

public func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!){
    print("Commit navigation")
}

public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!){
    print("Finish navigation")
}

public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error){   
    print("Fail navigation")
}

有興趣可以下載這個完成品:Download


0 Comments

發佈留言

Avatar placeholder

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *