#11WKWebView(KOV)
Published in
9 min readDec 8, 2022
Apple程式範例檔5
基本上是複製Apple程式範例檔的程式碼,但詳細打上自己的註解和開發者文件上的資料.畢竟唯有打上註解,分析理解後,東西才可能變成自己的東西.
程式功能:模擬網頁開啟的狀態
能開啟的網頁,當然就是我們的程式男神,情歌王子,swfit課程界的第一把交椅,彼得潘大神的Medium教室啦.讓我們先介紹會用到實作技術.
實作技術:
- WKWebView
- KOV(Key-Value Observing)
- webView的navigationDelegate
- UIAlertController
KOV(Key-Value Observing)是我第一次聽到技術,實際理解後,發現跟NotificationCenter有點像呢.不過KOV似乎比較陽春一點.基本上就是觀察某個特定的元件,當元件發生變化時,同步進行改動.
讓我們開始Coding吧!
寫好變數和資料
//用程式生成元件
var webView: WKWebView!
var progressView: UIProgressView!
//網頁名稱
var websites = ["medium.com/彼得潘的-swift-ios-app-開發教室","github.com","google.com"]
//顯示網頁
override func loadView() {
webView = WKWebView()
webView.navigationDelegate = self
view = webView
}
生成按鈕
//設計按鈕
override func viewDidLoad() {
super.viewDidLoad()
title = "網頁瀏覽器"
//右上角按鈕
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "開啟", style: .plain, target: self, action: #selector(openTapped))
//最下面的東西是WKNavigation
//空白按鈕
let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
//重新下載WebView
let refresh = UIBarButtonItem(barButtonSystemItem: .refresh, target: webView, action: #selector(webView.reload))
//上一頁
let back = UIBarButtonItem(barButtonSystemItem: .rewind, target: webView, action: #selector(webView.goBack))
//下一頁
let forward = UIBarButtonItem(barButtonSystemItem: .fastForward, target: webView, action: #selector(webView.goForward))
//任務條
progressView = UIProgressView(progressViewStyle: .default)
progressView.sizeToFit()
//把View加進Item
let progressButton = UIBarButtonItem(customView: progressView)
//按鈕陣列 底下的bar. webView
toolbarItems = [progressButton, back, forward, spacer, refresh]
//解開隱藏
navigationController?.isToolbarHidden = false
/*options 參數可以使用入以下內容:
new:表示更改字典應要提供新的屬性值(如果適用)
old:表示更改字典應要包含舊的屬性值(如果適用)
initial:如果指定,則在觀察者註冊方法返回之前應立即向觀察者發送通知。
prior:是否應該在每次更改前後向觀察者發送單獨的通知,而不是更改後的單個通知。*/
//KOV!!!!!!
//觀察WKWebView的estimatedProgress(估計進度)
webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)
//控制 前進或後退的手勢讓按鈕可以點擊
webView.allowsBackForwardNavigationGestures = true
}
右上角按紐執行的函式,其中又包含AlertAction的函式
@objc func openTapped() {
let ac = UIAlertController(title: "開啟網頁...", message: nil, preferredStyle: .actionSheet)
//按鈕
for website in websites {
ac.addAction(UIAlertAction(title: website, style: .default, handler: openPage))
}
ac.addAction(UIAlertAction(title: "取消", style: .destructive))
present(ac, animated: true)
}
// 是用UIAlertAction進行動作觸發
func openPage(action: UIAlertAction) {
guard let actionTitle = action.title else {
return
}
//有的話,設計成網址
if websites.contains(actionTitle) {
guard let url = URL(string:("https://" + actionTitle).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!) else {
return
}
//開啟網頁
webView.load(URLRequest(url: url))
}
}
KOV設值的部分!
/*keyPath
相對於object的金鑰路徑,與已更改的值相對於。
object
key Path的源物件。
change
描述對鍵路徑keyPath相對於object的屬性值所做的更改的字典。 條目在Change Dictionary Keys中描述。
context
觀察者註冊接收關鍵值觀察通知時提供的值。*/
//addObserver的設定值
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "estimatedProgress" {
//顯示進度條
progressView.progress = Float(webView.estimatedProgress)
//顯示估計網路載入
}
}
加碼附上 特定條件下 網站才能被開啟的函式
加了這行,彼得潘大神的網站就開不起來了.因為中文網址要轉碼,跟原先的網址就不一樣了
/*webView
導航請求開始的網路檢視。
navigationAction
有關觸發導航請求的操作的詳細資訊。
decidePolicyFor
方針
decisionHandler
一個完成處理程式塊,用於呼叫結果是否允許或取消導航。 此處理程式沒有返回值,並接受以下引數*/
//@escaping 取自函式外的參數
//開啟網站的方針
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
// 只有設定好的網址才能開啟
let url = navigationAction.request.url
if let host = url?.host {
for website in websites {
if host.contains(website) {
//允許開啟
decisionHandler(.allow)
return
}
}
//不允許開啟,跳出alert
let ac = UIAlertController(title: "這個網站被封鎖了", message: "請從網站列表選擇.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Open List of allowed websites", style: .default, handler: openPage))
present(ac,animated: true)
}
decisionHandler(.cancel)
}
程式連結:
參考資料: