---
# System prepended metadata

title: 【學習筆記】如何在 iOS APP 透過 SwiftUI 搭配 WKWebView 顯示網頁內容
tags: [Front-End, webview, ios]

---

[![hackmd-github-sync-badge](https://hackmd.io/fKnN7povSqit0jn2_RX6hw/badge)](https://hackmd.io/fKnN7povSqit0jn2_RX6hw)
###### `Front-End` `ios` `webview`
# 【學習筆記】如何在 iOS APP 透過 WKWebView 實現內嵌網頁功能

![](https://hackmd.io/_uploads/BJXLBiH6n.jpg)

> Photo by <a href="https://unsplash.com/@danielkorpai?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Daniel Korpai</a> on <a href="https://unsplash.com/photos/Y3LGWCsrgmg?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
  

## What is Webview？

Webview 其實就是一個精簡的瀏覽器，透過渲染引擎（Webkit）呈現網頁內容，中文又翻作「網頁視圖」。

和我們所熟悉的瀏覽器（例如：iOS / Safari 和 Android / Chrome）相比，最大差異在於，外觀介面沒有網址列、功能鍵等功能。

透過 Webview 實現的混合模式開發（Hyprid APP），相較於原生開發（Native APP），具備跨平台開發、開發效率高、降低成本、可離線執行等優點；然而，也須考量效能性、安全性與兼容性等問題。

## iOS APP 顯示網頁的三種方式

iOS SDK 提供三種方式，讓開發者用來顯示網頁內容：

### 透過 [UIApplication](https://developer.apple.com/documentation/uikit/uiapplication/) 外開網頁視窗

`UIApplication.shared.open` 是 Swift 中的一個 API，功能是可暫時離開當前 APP，開啟指定的 URL。

```swift=
import SwiftUI
struct ContentView: View {
    
    var body: some View {
        Button(action: {
            let url = URL(string: "https://heidiliu2020.github.io/")!
            UIApplication.shared.open(url)
        }) {
            Text("點我前往連結")
        }
    }
}
```

### [WKWebView](https://developer.apple.com/documentation/webkit/wkwebview)

和 Android 的 Webview 元件類似，iOS 同樣有 Webview 能用來顯示網頁內容。

而在 iOS 的 WebView 分為 UIWebView 和 iOS 8+ 新增的 WKWebView 兩種類型。

WebKit 框架中的 WKWebView 相較於前者，在於性能與穩定性的提升，具備 Nitro JavaScript 引擎的等優點。並透過 `UIViewRepresentable` 協定包裝 View，顯示特定的網頁內容。

```swift=
import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    
    func makeUIView(context: Context) -> some UIView {
        // return UIView object
    }
    
    func updateUIView(_ uiView: some UIView, context: Context) {
        // update UIView
    }
}
```

使用上需注意 WKWebView 沒有內建的 Back & Forward 按鍵，若需提供返回歷史頁面等功能，必須自行開發一個自訂的網頁瀏覽器。

### [SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller/)

相較於 WKWebView 的限制，iOS 9 中導入的控制器 SFSafariViewController，能使用與 Safari 瀏覽器相同的功能，例如切換上下頁。

方法是透過 `UIViewControllerRepresentable` 協定定義 SwiftUI view 型別，將 SFSafariViewController 包裝成 SwiftUI view，即可顯示網頁內容。

```swift=
import SwiftUI
import SafariServices

struct SafariView: UIViewControllerRepresentable {
    // TODO...
}
```

## 實戰練習

### Step1. 環境架設：安裝 XCode

首先進入[官網下載頁面](https://developer.apple.com/download/applications/)，登入後選擇要下載 XCode 版本。

![](https://hackmd.io/_uploads/BJ0BxoST3.png)

不同版本的 XCode，在使用上須考慮開發環境、APP 套件與 iOS 版本相容性，若需要安裝特定版本的 XCode，可參考這篇文章：[如何手動快速下載不同版本的Xcode - Poy Chang](https://blog.poychang.net/manually-download-multiple-versions-of-xcode/)。

### Step2. 建立新專案

運行 XCode 後，點擊「Create a new Xcode project」建立新專案。

![](https://hackmd.io/_uploads/B1ST1sB63.png)

接著點選 APP 建立專案範本，內建範本有預設程式碼，能夠協助快速開發：

![](https://hackmd.io/_uploads/HkRefsBan.png)

### Step3. 利用 UIViewRepresentable 協定調用 WKWebView

接著透過 `UIViewRepresentable` 協定包裝 View，顯示指定的網頁內容：

+ ContentView.swift

```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        WebView(url: URL(string: "https://heidiliu2020.github.io/")!)
            .edgesIgnoringSafeArea(.all)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
```

+ SwiftUIView.swift

```swift=
import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    let url: URL

    func makeUIView(context: Context) -> WKWebView  {
        let wkwebView = WKWebView()
        wkwebView.load(URLRequest(url: url))
        return wkwebView
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
    }
}
```

### Step4. [Building and running an app](https://developer.apple.com/documentation/xcode/building-and-running-an-app)

最後是運行 APP 驗證結果，點選上方的開始鍵執行 Building，點開右側的選單可選擇要運行的裝置版本，或是透過傳輸線連接在實體機上進行測試。

![](https://hackmd.io/_uploads/BkG1Usrpn.png)

## 小結

同樣是因為專案上的測試需求，沒想到這回又再次把 Xcode 安裝回電腦中，也許因為過去曾稍微接觸過一點，這回相對沒那麼迷惘。

能夠直接把 APP Build 到實體手機測試，和透過 XCode 模擬器終究還是有很大區別，雖然要實際上架到 App Store 需要課金，但以現階段而言也已經很夠用了。回顧過去所接觸的知識，似乎明白儘管當初一知半解，只要再多經歷幾次也能夠好好運用這些技術了。

## Reference

+ [使用 UIViewRepresentable 協定　讓你輕鬆建立 SwiftUI TextView](https://www.appcoda.com/swiftui-textview-uiviewrepresentable/)
+ [利用 UIViewControllerRepresentable 協定　在 SwiftUI 存取相簿並使用相機](https://www.appcoda.com.tw/swiftui-camera-photo-library/)
