Skip to Content

WKWebView 功能測試 (上) - 建置、設定、呈現

 

以前 Mac 程式內建的瀏覽器元件是用 WebView,iOS 則是用 UIWebView,而現在最新的是用 WKWebView,不過文中若提到 WebView 通常就是指 WKWebView,除非有特別強調是指舊版的框架。

建置 WKWebView

因為直接使用 WebView 元件似乎會有問題,在 Xcode 上雖然可以執行,但是直接由 APP 執行就看不到 WebView,所以採用使用 code 來建置 WebView。

底下的 code 是 copy 來的,黑色是原來就有的,紅色是後來加上去的。

 

import Cocoa

import WebKit

 

class ViewController: NSViewController, WKUIDelegate, WKNavigationDelegate {

 

    let webView = WKWebView()

    

    override func viewDidLoad() {

        super.viewDidLoad()

 

        // Do any additional setup after loading the view.

        

        self.webView.uiDelegate = self

        self.webView.navigationDelegate = self

        webView.frame = CGRect(x:0,y:0,width:400,height: 270)

        view.addSubview(webView)

                

        let myURL=URL(string: "https://www.apple.com")

        let myRequest = URLRequest(url: myURL!)

        webView.load(myRequest)

    }

 

    override var representedObject: Any? {

        didSet {

        // Update the view, if already loaded.

        }

    }

}

 

只有建置 WebView 是無法連線的,還要開啟網路的功能才行。

如下圖,選擇專案 -> TARGETS -> Signing... -> App Sandbox

開啟 Netword 的 Outgoing Connections (Client)

設定之後再次執行,就可以看到成果了。

設定 WebView 位置

接下來要設計 WebView 的位置,因為它不是在 Storyboard 處理的,無法在 Storyboard 上使用工具調整,需要用程式碼來處理。

我希望它是幾乎滿框,但上面要留一小段空間放置一些元件。

在 MS Window 寫程式時,我大概就是先放一個 Panel,讓它高度固定並置頂,再放 WebView 填滿整個 Client 就可以了。

在 Mac 中,目前知道的是採用自動布局的「約束」(Constraint),也就是某個元件某個值要和另一個元件某個值保持某種關係。[官方文件]

例如我希望 WebView 的左邊要和視窗的左邊保持 20px。

在 MS Window 程式,就是在 Windows 的 OnResize 視事件中撰寫

webview->left = 20 (這是相對主視窗的)

Mac 的做法就是建立一個約束:

 

let ctLeft = NSLayoutConstraint(

item: webView, // webView 這個元件

attribute: .leading, // 的左邊

relatedBy: .equal, // 要等於

toItem: self.view, // 主視窗

attribute: .leading, // 的左邊

multiplier: 1, // x 1

constant: 20) // 再加 20

 

.leading 是左邊,.trailing 是右邊。上面紅色的註解就是各屬性的說明。用程式碼來描述大概就是

webView.left = (self.view.left * 1) + 20

這張是 [官方文件] 裡面的圖,也可以參考它的邏輯。

程式碼看起來雖然有點囉嗦,但在 Xcode 上函式參數都自動填好了,只要填進去我們要的資料,也算是方便。

就依上面的方法,建立好四邊的約束之後,再執行

 

self.view.addConstraint(ctLeft)

self.view.addConstraint(ctRight)

self.view.addConstraint(ctTop)

self.view.addConstraint(ctBottom)

 

就把四條約束加進去了。

也可以採用這個方式來處理:

NSLayoutConstraint.activate([ctLeft, ctRight, ctTop, ctBottom])

以上完成後,要記得要加上底下這行,理由後面會談到。

webView.translatesAutoresizingMaskIntoConstraints = false

這是完成的原始碼,因為有約束,所以初始大小就不重要了,所以可以設定 webView.frame = .zero

 

webView.frame = .zero

self.view.addSubview(webView)

 

webView.translatesAutoresizingMaskIntoConstraints = false

        

let ctLeft = NSLayoutConstraint(item: webView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1, constant: 20)

 

let ctRight = NSLayoutConstraint(item: webView, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1, constant: -20)

 

let ctTop = NSLayoutConstraint(item: webView, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1, constant: 50)

 

let ctBottom = NSLayoutConstraint(item: webView, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: -20)

        

self.view.addConstraint(ctLeft)

self.view.addConstraint(ctRight)

self.view.addConstraint(ctTop)

self.view.addConstraint(ctBottom)    

 

// NSLayoutConstraint.activate([ctLeft, ctRight, ctTop, ctBottom])

 

這是完成的畫面,上面空間較大,我放了二個元件,左、右、下各 20 點的距離。

約束還有不少做法,例如我希望 WebView 的寬度等於主視窗的寬度,就不用設定左右邊界,直接設定寬度,約束就可以少一項,如下:

 

let ctWidth = NSLayoutConstraint(item: webView, attribute: .width, relatedBy: .equal, toItem: self.view, attribute: .width, multiplier: 1, constant: 0)

        

self.view.addConstraint(ctWidth)   

self.view.addConstraint(ctTop)

self.view.addConstraint(ctBottom)      

 

// NSLayoutConstraint.activate([ctWidth, ctTop, ctBottom])

 

這裡要說明一些注意事項:

在沒有任何約束時,主畫面若拉大,WebView 都是固定在左下角,因為它是以左下角為原點座標,並且 WebView 有固定大小。

一開始測試時,我只設了右邊的約束,原本以為如此一來,左右都會保持固定的距離,結果卻變成視主窗無法調整寬度。

原來是因為 WebView 已經有座標,也有長和寬了,再加上右邊又與主視窗有約束,主視窗就不能拉了,否則不是約束失效,就是 WebView 寬度改變,這都是不符合原先的要求。

所以 Google 了一下,才知道要加上這一行:

webView.translatesAutoresizingMaskIntoConstraints = false

問題又來了,當我加入這一行之後,執行畫面就看不到 WebView 了。

又做了不少測試,到處翻資料,才知道約束的設計要齊全,因為已經加了那一行,表示目前要採用約束布局,先前規畫的布局已經失效了,若此時約束不夠齊全,有些資訊不足,就無法呈現合理的畫面。

所以要乖乖的將所有的約束都設計好,果然這樣就能正確呈現了。

載入文件

我在 Mac 上要寫的程式主要是由 WebView 載入本地文件,所以我把載入網頁的程式改成載入文件。

let myURL=URL(string: "https://www.apple.com")

改成

let myURL=URL(string: "file:///Users/heaven/desktop/index.htm")

結果打開一看,一片空白。

Xcode 有這樣的訊息,看起來是因為文件在沙箱 (sandbox) 之外,因此不允許讀取。

我查了一些資料,也還沒搞定如何處理,所以我依某些網頁的建議把設定中的沙箱刪除了,也就是點選底下紅框的位置。

然後再執行,系統就跳出詢問視窗。

選擇同意後,就可以看到底下的測試畫面了。

以上畫面有外部 css、js,以及內部的 css 和 js,還有連結,目前測試功能皆正常。

載入檔案系統的網頁還可以用 loadFileURL 的功能,如下:

 

webView.loadFileURL(URL(string: "file:///Users/heaven/desktop/html/index.htm")!, allowingReadAccessTo: URL(string: "file:///Users/heaven/desktop/html")!)

 

以上我加入一層 html 目錄。

經測試結果,若把外部的 css 和 js 放在 destop 目錄中,而 allowingReadAccessTo 卻是 desktop/html 就會無法載入,因為 css 和 js 在允許的目錄之外,除非把 allowingReadAccessTo 設定至 desktop 就沒有問題了。

回應

發表新回應

這個欄位的內容會保密,不會公開顯示。
  • 自動將網址與電子郵件地址轉變為連結。
  • 自動斷行和分段。
  • 可使用的 HTML 標籤:<a> <address> <b> <blockquote> <br> <caption> <center> <cite> <code> <dd> <del> <div> <dl> <dt> <em> <h1> <h2> <h3> <h4> <h5> <h6> <hr> <i> <img> <ins> <li> <ol> <p> <pre> <span> <strike> <strong> <sub> <sup> <table> <tbody> <td> <th> <tr> <u> <ul>
    Allowed Style properties: background, background-attachment, background-color, background-image, background-position, background-repeat, border, border-bottom, border-bottom-color, border-bottom-style, border-bottom-width, border-collapse, border-color, border-left, border-left-color, border-left-style, border-left-width, border-right, border-right-color, border-right-style, border-right-width, border-spacing, border-style, border-top, border-top-color, border-top-style, border-top-width, border-width, bottom, caption-side, clip, color, direction, empty-cells, font, font-family, font-size, font-size-adjust, font-stretch, font-style, font-variant, font-weight, height, left, letter-spacing, line-height, list-style, list-style-image, list-style-position, list-style-type, margin, margin-bottom, margin-left, margin-right, margin-top, max-height, max-width, min-height, min-width, overflow, padding, padding-bottom, padding-left, padding-right, padding-top, right, table-layout, text-align, text-decoration, text-indent, text-transform, top, unicode-bidi, vertical-align, white-space, width, word-spacing, z-index

更多關於格式選項的資訊

CAPTCHA
驗證碼只有阿拉伯數字, 這是躲廣告用的, 麻煩你輸入了.
Image CAPTCHA
Enter the characters shown in the image.


story | about seo