iOS開發基礎117-Hybrid

Mr.陳發表於2024-07-17

Hybrid

Hybrid(混合)開發是一種結合了Web技術和原生應用開發技術的方法,旨在簡化跨平臺應用開發。透過Hybrid開發,開發者可以用HTML、CSS和JavaScript等前端技術編寫程式碼,並將其執行在一個內嵌的瀏覽器環境中,從而實現跨平臺的移動應用。

什麼是Hybrid開發?

Hybrid開發主要是指將應用的使用者介面和業務邏輯部分用Web技術(HTML、CSS、JavaScript)編寫,然後透過一箇中間層(通常是內嵌的瀏覽器WebView)在移動裝置上執行。這樣做的主要目標是“一次開發,多平臺執行”,即可以用一套程式碼同時支援iOS、Android等多個平臺。

Hybrid開發的核心元件

  1. WebView:

    • Hybrid應用通常執行在一個內嵌的瀏覽器環境中,這個環境就是WebView。WebView是一個可以在原生應用中嵌入網頁瀏覽器的元件,能夠解析和執行HTML、CSS和JavaScript等Web標準技術。
    • 在iOS平臺,常用的是UIWebView或WKWebView(推薦用WKWebView,因為效能更好)。
    • 在Android平臺,常用的是WebView元件。
  2. JavaScript Bridge(JS橋樑):

    • JavaScript Bridge是Hybrid應用中Web和原生部分通訊的橋樑。透過JS Bridge,JavaScript可以呼叫原生程式碼,原生程式碼也可以呼叫JavaScript,從而實現兩者之間的資料互動。
    • 這種雙向通訊使得Web部分能夠呼叫裝置的原生功能(如相機、地理位置、儲存等),從而突破Web技術的限制。
  3. Hybrid框架:

    • 經典的Hybrid開發框架有Cordova(以及其廠商版本PhoneGap)、Ionic等。它們提供了WebView封裝、JavaScript Bridge以及一系列外掛和API,使得開發者可以更方便地呼叫裝置的原生功能。
    • 例如:Cordova外掛庫提供訪問裝置硬體和其他功能的外掛,Ionic提供了一整套UI元件庫和工具鏈,極大地簡化了Hybrid開發的流程。

Hybrid開發的常見框架

1. Apache Cordova/PhoneGap

Apache Cordova 是一個開源的移動開發框架,它允許開發者使用HTML5、CSS3和JavaScript建立跨平臺的移動應用。PhoneGap是Adobe公司提供的Cordova的一個商業版本。

底層原理
  • WebView容器: Cordova建立了一個原生的應用容器,該容器內嵌了一個WebView,用於執行Web應用。
  • JavaScript APIs: Cordova提供了一系列JavaScript APIs,讓Web應用可以呼叫原生功能,如相機、檔案系統等。
  • 外掛機制: Cordova有一個龐大的外掛庫,開發者可以使用這些外掛擴充套件應用的功能,也可以開發自定義外掛。
document.addEventListener('deviceready', function() {
    console.log('Device is ready');
    // 呼叫原生相機
    navigator.camera.getPicture(onSuccess, onFail, { 
        quality: 50,
        destinationType: Camera.DestinationType.DATA_URL
    });
}, false);

function onSuccess(imageData) {
    var image = document.getElementById('myImage');
    image.src = "data:image/jpeg;base64," + imageData;
}

function onFail(message) {
    alert('Failed because: ' + message);
}
優缺點
優點
  • 跨平臺: 一次開發,多平臺使用。
  • 豐富的外掛庫: 大量的外掛可以方便地訪問裝置功能。
  • 活躍的社群支援: 豐富的社群資源和支援。
缺點
  • 效能問題: 由於依賴WebView,有時效能不如完全原生應用。
  • 複雜的除錯: WebView和原生程式碼的混合除錯相對複雜。
  • 使用者體驗: 在UI和使用者體驗上,有時不如完全原生的流暢。

2. Ionic

Ionic 是一個基於Cordova構建的前端框架,它提供了豐富的UI元件庫和工具鏈,使得開發者可以更容易地建立高質量的Hybrid應用。

底層原理
  • Ionic框架: 提供了一系列的UI元件和工具,可與Angular等框架整合,極大地簡化了開發。
  • Cordova整合: Ionic實際執行在Cordova之上,利用Cordova提供的外掛和API來訪問裝置功能。
  • 自定義主題: 提供豐富的主題和樣式,可以靈活定製。
import { Camera, CameraOptions } from '@ionic-native/camera/ngx';

constructor(private camera: Camera) { }

takePicture() {
  const options: CameraOptions = {
    quality: 100,
    destinationType: this.camera.DestinationType.FILE_URI,
    encodingType: this.camera.EncodingType.JPEG,
    mediaType: this.camera.MediaType.PICTURE
  };

  this.camera.getPicture(options).then((imageData) => {
    let base64Image = 'data:image/jpeg;base64,' + imageData;
  }, (err) => {
    console.log(err);
  });
}
優缺點
優點
  • 優質的UI元件: 提供了豐富而專業的UI元件庫,適合快速開發。
  • 與Angular高度整合: 適合熟悉Angular的開發者。
  • 全面的文件和社群支援: 擁有豐富的教程和活躍的社群。
缺點
  • 效能限制: 同樣依賴WebView,效能可能不如原生應用。
  • 學習曲線: 對那些不熟悉Angular的開發者來說,可能需要適應。

Hybrid開發的優缺點

優點

  1. 跨平臺: 只需一次開發即可在多個平臺上執行,節省開發時間和成本。
  2. 快速開發和部署: 利用Web技術,可以快速迭代開發和部署。
  3. 程式碼可重用: 大量程式碼和邏輯可以在多個平臺間共享,減少重複工作。
  4. 靈活性: 可以利用各種Web技術和工具,同時也可以呼叫裝置的原生功能。

缺點

  1. 效能問題: Hybrid應用的效能通常不如完全原生應用,但透過最佳化可以改善。
  2. 使用者體驗: 在一些高互動、高效能要求的應用中,使用者體驗可能不如原生應用。
  3. 除錯複雜: 由於涉及Web和原生程式碼的混合,除錯可能更復雜。
  4. 依賴第三方框架和工具: 雖然這些工具提供了方便,但也帶來了額外的學習和維護成本。

小結

Hybrid開發是移動應用開發的一種重要方法,透過結合Web技術和原生技術,可以快速開發跨平臺應用,尤其適合一些業務邏輯複雜、UI互動要求較低的應用場景。然而,開發者需要根據具體的專案需求和技術棧選擇合適的開發方式,有時完全原生開發或其他方法(如React Native、Flutter)可能更適合。瞭解並掌握Hybrid開發及其原理,可以幫助開發者在不同場景下做出更好的技術決策。

iOS專案中接入Hybrid

在iOS專案中,接入Hybrid框架(如Cordova、Ionic)通常涉及多個步驟,包括專案建立、新增平臺、安裝外掛、配置WebView等。以下是一個詳細深入的指南,介紹如何在iOS專案中接入Hybrid框架,並解釋其底層實現原理。

1. 使用Cordova接入iOS專案

環境準備

首先,需要確保已安裝以下工具:

  • Node.js 和 npm(Node 包管理器)
  • Cordova CLI

透過命令列進行安裝:

# 安裝 Cordova
npm install -g cordova

建立專案

接下來,使用Cordova CLI建立一個新的Cordova專案:

# 建立一個新的 Cordova 專案
cordova create MyHybridApp com.example.myhybridapp MyHybridApp
cd MyHybridApp

新增iOS平臺

然後,新增iOS平臺支援:

# 新增 iOS 平臺
cordova platform add ios

編寫Web部分程式碼

在專案目錄下的 www 資料夾中,你可以編寫HTML、CSS和JavaScript程式碼,這部分程式碼將執行在WebView中。

例如,建立一個簡單的 index.html 檔案:

<!DOCTYPE html>
<html>
<head>
    <title>My Hybrid App</title>
    <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript">
        document.addEventListener('deviceready', function() {
            console.log('Cordova is ready');
        }, false);
    </script>
</head>
<body>
    <h1>Welcome to My Hybrid App!</h1>
</body>
</html>

安裝外掛

Cordova外掛可以讓你訪問裝置的原生功能。透過以下命令安裝相機外掛:

# 安裝相機外掛
cordova plugin add cordova-plugin-camera

在JavaScript程式碼中呼叫這個外掛:

<!DOCTYPE html>
<html>
<head>
    <title>My Hybrid App</title>
    <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript">
        document.addEventListener('deviceready', function() {
            document.getElementById('takePictureButton').addEventListener('click', takePicture);
        }, false);

        function takePicture() {
            navigator.camera.getPicture(onSuccess, onFail, { 
                quality: 50,
                destinationType: Camera.DestinationType.DATA_URL
            });
        }

        function onSuccess(imageData) {
            var image = document.getElementById('myImage');
            image.src = "data:image/jpeg;base64," + imageData;
        }

        function onFail(message) {
            alert('Failed because: ' + message);
        }
    </script>
</head>
<body>
    <h1>Welcome to My Hybrid App!</h1>
    <button id="takePictureButton">Take Picture</button>
    <img id="myImage" />
</body>
</html>

構建並執行

最後,構建專案並在iOS模擬器或裝置上執行:

# 構建 iOS 專案
cordova build ios

# 執行 iOS 專案
cordova emulate ios

底層實現原理

WebView

在Cordova環境中,核心元件是WebView。WebView是一個在原生應用中嵌入瀏覽器功能的元件,用於載入和執行Web內容。在iOS上,早期使用的是 UIWebView,而現在推薦使用效能更好的 WKWebView

  • UIWebView: 傳統的WebView元件,但不推薦使用,因為效能較差。
  • WKWebView: 現代WebView元件,效能和穩定性更好。

WKWebView 透過載入HTML內容,將Web應用嵌入到原生應用中。你可以在Xcode工程中手動新增 WKWebView 元件或使用Cordova自動生成的模板。

JavaScript Bridge

JavaScript Bridge是Cordova實現的重要部分,它允許JavaScript與原生程式碼之間進行通訊。具體實現通常包括:

  1. 外掛機制: Cordova外掛透過定義JavaScript介面和對應的原生程式碼實現,提供對裝置功能的訪問。例如,cordova-plugin-camera外掛將JavaScript呼叫對映到原生相機API。
navigator.camera.getPicture(onSuccess, onFail, options);
  1. 訊息傳遞: 當JavaScript呼叫外掛介面時,會生成一個訊息,將其傳遞給原生層。例如在iOS上,Cordova透過Objective-C/Swift程式碼監聽這些訊息,並呼叫相應的原生API。結果再透過相同的機制傳回JavaScript環境。
// Example Objective-C method to handle JavaScript call
- (void)getPicture:(CDVInvokedUrlCommand*)command {
    // Call native camera API
}
  1. 呼叫原生API: 原生層實現具體功能,如呼叫相機、獲取位置等。實現結果透過JavaScript Bridge返回JavaScript環境。例如,使用 CDVPluginResult 將結果返回給JavaScript。
// Send result back to JavaScript
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:imageBase64];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];

外掛機制

Cordova的外掛機制非常靈活,允許開發者定義和使用自定義外掛。當安裝外掛時,Cordova會將外掛程式碼複製到專案中,並更新配置檔案以確保外掛被正確載入。例如安裝cordova-plugin-camera外掛時,Cordova會在專案中載入對應的JavaScript介面和原生程式碼實現。

構建工具鏈

Cordova有一套完整的工具鏈,用於管理專案、平臺和外掛。主要工具包括:

  • cordova create: 建立新專案。
  • cordova platform add: 新增平臺,如iOS或Android。
  • cordova plugin add: 安裝外掛。
  • cordova build: 構建專案。
  • cordova run/cordova emulate: 執行或模擬專案。

這些工具簡化了開發過程,使得開發者可以專注於應用邏輯和使用者介面,而無需處理繁瑣的原生程式碼細節。

小結

透過以上步驟,你可以在iOS專案中成功接入Cordova,同時瞭解其底層實現細節,包括WebView的使用、JavaScript和原生程式碼的通訊機制(JavaScript Bridge)、外掛機制等。藉助Cordova,你可以輕鬆實現一次開發,跨平臺執行,提高開發效率,降低維護成本。希望這篇指南能夠幫助你更好地理解和應用Hybrid開發技術。

WKWebView的接入

作為 iOS 開發人員,如果你需要在 WKWebView 上處理特定的業務邏輯,需要涉及以下幾個步驟:

  1. 初始化 WKWebView:

    • 配置 WKWebView
    • 在檢視控制器中新增並展示 WKWebView
  2. 實現與 JavaScript 的互動:

    • 配置 WKScriptMessageHandler 處理 JavaScript 發出的訊息。
    • 使用 evaluateJavaScript 方法從原生程式碼執行 JavaScript 指令碼。
  3. 管理請求和導航:

    • 實現 WKNavigationDelegate 以管理載入狀態和導航決策。

下面是一個具體的程式碼例項,展示如何在 WKWebView 中處理這些步驟。

1. 初始化 WKWebView

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler {

    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // 建立 WKWebView 配置
        let webConfiguration = WKWebViewConfiguration()
        
        // 新增 JavaScript 訊息處理器
        webConfiguration.userContentController.add(self, name: "iosHandler")

        // 初始化 WKWebView 並設定導航代理
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.navigationDelegate = self
        
        // 設定 WebView 的約束
        view.addSubview(webView)
        webView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            webView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            webView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            webView.topAnchor.constraint(equalTo: view.topAnchor),
            webView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
        
        // 載入本地或遠端 HTML
        if let url = Bundle.main.url(forResource: "index", withExtension: "html") {
            webView.loadFileURL(url, allowingReadAccessTo: url)
        }
    }

    // 處理 JavaScript 發出的訊息
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "iosHandler", let messageBody = message.body as? String {
            print("Received message from JavaScript: \(messageBody)")
            // 在這裡處理來自 JavaScript 的訊息
        }
    }
}

在這個示例中:

  • 初始化 WKWebView:我們建立了一個 WKWebViewConfiguration 物件,並設定了一個訊息處理器(iosHandler)。
  • 新增約束:確保 WKWebView 填滿整個檢視控制器的檢視。
  • 載入 HTML:從本地載入一個 index.html 檔案。如果需要載入遠端 URL,可以替換為 webView.load(URLRequest(url: URL))

2. 與 JavaScript 互動

為了在 WKWebView 中與 JavaScript 互動,你需要在 HTML 檔案中編寫 JavaScript 程式碼,並在需要時傳送訊息給原生程式碼。

在你的 index.html 檔案中,編寫如下 JavaScript 程式碼:

<!DOCTYPE html>
<html>
<head>
    <title>WKWebView Example</title>
</head>
<body>
    <h1>Hello from WebView</h1>
    <button onclick="sendMessageToiOS()">Send Message to iOS</button>

    <script type="text/javascript">
        function sendMessageToiOS() {
            if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.iosHandler) {
                window.webkit.messageHandlers.iosHandler.postMessage('Hello from JavaScript');
            }
        }
    </script>
</body>
</html>

3. 管理請求和導航

為了更好地管理 WKWebView 的導航過程,你還可以實現 WKNavigationDelegate 的相關方法:

extension ViewController {

    // 頁面開始載入時呼叫
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        print("Page started loading")
    }

    // 頁面載入成功時呼叫
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("Page finished loading")
    }

    // 頁面載入失敗時呼叫
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        print("Page failed to load: \(error.localizedDescription)")
    }

    // 攔截請求並決定是否允許導航
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        let url = navigationAction.request.url
        
        if url?.scheme == "https" && url?.host == "safe.example.com" {
            decisionHandler(.allow)
        } else {
            decisionHandler(.cancel)
        }
    }
}

在這個擴充套件中:

  • didStartProvisionalNavigation: 當頁面開始載入時呼叫,可以在這裡實現載入指示器等。
  • didFinish: 當頁面載入完成時呼叫,可以在這裡隱藏載入指示器等。
  • didFail: 當頁面載入失敗時呼叫,可以在這裡處理錯誤資訊。
  • decidePolicyFor: 攔截每個URL請求,並決定是否允許導航。你可以根據URL的scheme、host等屬性來決定是否允許載入該請求。

4. 從原生程式碼執行 JavaScript

如果你需要從原生程式碼中執行 JavaScript,例如將一些資料傳遞給網頁,或者呼叫網頁中的特定函式,可以使用 evaluateJavaScript 方法:

func executeJavaScript() {
    let script = "document.body.style.backgroundColor = '#FF0000';"
    webView.evaluateJavaScript(script) { (result, error) in
        if let error = error {
            print("Error executing JavaScript: \(error.localizedDescription)")
        } else {
            print("JavaScript executed successfully")
        }
    }
}

在這個示例中,我們將頁面的背景顏色更改為紅色。

小結

透過以上步驟,你可以在 iOS 專案中有效地使用 WKWebView,並實現與 JavaScript 的雙向互動。在實際專案中,隨著業務需求的複雜化,可能需要進一步處理更多的 JavaScript 訊息或更復雜的導航邏輯。但是,透過掌握上述基礎知識和程式碼示例,你已經可以開始在 iOS 應用中使用 WKWebView 實現許多常見的需求。

還沒完

透過上述 WKWebView 的基本處理,可以實現與 JavaScript 的雙向互動,但這只是實現 Hybrid 應用的基礎步驟。Hybrid 混合開發真正的意義在於將 Web 技術與原生技術相結合,以實現跨平臺的一次開發多次釋出。要實現一個完整的 Hybrid 應用,還需要考慮以下幾點:

1. 完整的 Hybrid 框架

藉助像 Cordova、Ionic 等框架,你可以更方便地管理平臺、外掛,並實現許多複雜的功能。這些框架提供了一套完整的工具鏈和外掛庫,大大簡化了開發和整合過程。

2. 外掛機制

為了充分利用裝置的原生功能(如相機、GPS、加速計等),需要完整的外掛機制。雖然你可以手動在 WKWebView 中實現部分功能,但成熟的 Hybrid 框架已經為你封裝好了各種外掛,可以極大地提高開發效率。

3. 跨平臺能力

Hybrid 應用的一個核心優勢是跨平臺能力。透過使用框架,你可以一次編寫程式碼,然後構建、釋出到多個平臺(如 iOS 和 Android),這比僅僅基於 WKWebView 的解決方案更具優勢。

4. 專案構建和管理工具

Hybrid 框架提供了豐富的工具鏈,用於專案管理、平臺構建和外掛安裝。如 Cordova 提供的 cordova-cli,可以方便地建立、管理和構建專案。

透過 Cordova 實現完整的 Hybrid 應用

下面是一個透過 Cordova 實現更完整的 Hybrid 應用的示例過程:

1. 安裝 Cordova

npm install -g cordova

2. 建立一個新的 Cordova 專案

cordova create MyHybridApp com.example.myhybridapp MyHybridApp
cd MyHybridApp

3. 新增 iOS 平臺

cordova platform add ios

4. 新增外掛

cordova plugin add cordova-plugin-camera

5. 編寫 HTML 和 JavaScript 程式碼

www 資料夾中編寫 HTML 和 JavaScript 程式碼(同前面示例中的 index.html)。

6. 構建並執行

cordova build ios
cordova emulate ios

Cordova 內部實現的補充

  • 多平臺支援:透過 cordova platform add,可以輕鬆新增 Android、iOS 等多種平臺。
  • 外掛管理:透過 cordova plugin add,方便地新增和管理各種外掛,以訪問原生裝置功能。
  • 專案構建:透過 cordova build,可以生成目標平臺的應用包。框架內部會處理很多繁瑣的配置和依賴管理工作。

更復雜的外掛開發

如果需要實現更復雜的功能,可以開發自定義的 Cordova 外掛,並在專案中引用。例如,如果你需要訪問特定的硬體裝置或第三方SDK,可以透過建立外掛,把這些功能封裝在外掛中,然後在專案中呼叫。

一個完整的自定義外掛示例

  1. 建立外掛目錄結構
cordova plugin create my-plugin --id cordova-plugin-myplugin --version 1.0.0
  1. 實現外掛的 iOS 部分
    src/ios 目錄下建立相應的 Swift 或 Objective-C 檔案,實現原生程式碼。

  2. 新增外掛到專案

cordova plugin add path/to/my-plugin

總結

雖然你可以手動使用 WKWebView 實現一些 Hybrid 應用的功能,但更推薦的方法是使用成熟的 Hybrid 框架如 Cordova 或 Ionic。這些框架提供了豐富的工具鏈和外掛庫,可以大大簡化開發、提升效率,並確保應用的跨平臺能力。透過結合這些框架,你將能夠更全面地開發高效且功能豐富的 Hybrid 應用。

相關文章