エンジニアのはしがき

プログラミングの日々の知見を書き連ねているブログです

Swiftでガワネイティブなアプリを作ろう!

f:id:tansantktk:20210224211159p:plain

ネイティブアプリでUIを作り込もうとすると何かと仕様について調べることが多く、苦労することが多いと思います。 個人的な意見ですが、今まで慣れ親しんだHTML, js, cssとは勝手が違い、Swiftでは思うようなUIを実現することが出来ず頭を抱えました🤢

WebViewを使えばネイティブアプリ上にブラウザ機能を貼り付けてしまうことが可能です。俗に言うガワネイティブというやつです。

要件にもよりますが、WebViewの活用は開発者の負荷を減らすことにも繋がります。 今回はSwiftでガワネイティブなアプリの作り方を公開していきたいと思います!

動作環境

  • macOS Big Sur (11.2.1)
  • XCode12.4
  • ビルド対象: iOS 13.2

ファイル構成

  • ViewController.swift
    • WebViewを描写するメソッドを呼び出す
  • RenderWkWebView.swift
    • WebView描写における具体的処理を記述する

ソースコード

ViewControllerでWkWebViewの描写処理を呼び出します。

ViewController.swift

import WebKit
import UIKit

class ViewController: UIViewController {
    let wkWebView = WKWebView()

    override func viewDidLoad() {
        super.viewDidLoad()

        // WebViewを描写。初期表示するページはtargetUrlに指定する。
        self.renderWkWebView(wkWebView: wkWebView, targetUrl: "https://www.google.com/")
    }
}

WkWebViewの描写処理の具体的な処理は、RenderWkWebView.swiftにファイル分割して記述します。 Swiftのextentionを使えば、classにメソッドを後付けすることが出来ます。

その名の通り、機能拡張をする為の仕様です。 同じclassで書きたいけど記述が長くなりそうな時には有効活用できると思います。

RenderWkWebView.swift

import UIKit
import WebKit

extension ViewController {
    /// WkWebViewを描写 
    public func renderWkWebView(wkWebView: WKWebView, targetUrl: String) -> Void {
        // 端末の向き変更時にも画面いっぱい表示されるよう指定する
        wkWebView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        // WkWebViewの読み込み
        view.addSubview(wkWebView)
        wkWebView.frame = view.frame
        wkWebView.navigationDelegate = self
        wkWebView.uiDelegate = self
        // WebViewの上下端でスワイプした際のスクロールを禁止
        wkWebView.scrollView.bounces = false
        // 重なり順を最背面に
        self.view.sendSubviewToBack(wkWebView)
        
        // WebView内でのピンチイン・ピンチアウトによるズームを禁止
        let restrictZoom: String = "var meta = document.createElement('meta');" +
                                    "meta.name = 'viewport';" +
                                    "meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no';" +
                                    "var head = document.getElementsByTagName('head')[0];" + "head.appendChild(meta);";
        let restrictZoomScript: WKUserScript = WKUserScript(source: restrictZoom, injectionTime: .atDocumentEnd, forMainFrameOnly: true)

        let urlRequest = URLRequest(url:URL(string: targetUrl)!)
        // 指定したURLをWebViewで表示する
        wkWebView.load(urlRequest)
    }
}

↑で記述している内容は、画面いっぱいにWebViewを表示するケースを想定しています。

iOSの場合、端末の向きを変えたりスワイプ、ピンチイン・ピンチアウトといった操作をされるとレイアウトが崩れる為、制御をしています。 要件に応じて、制御する内容は変えていただければと思います。

Appleのアプリ審査の問題

確定情報ではありませんが、単純にWebViewを張り付けただけのiOSアプリは審査時にAppleから弾かれる可能性があります。

審査対策

iOSアプリにナビバーを別途追加し、操作説明の画面を表示させる機能を追加したことで、Apple審査を通過させることができました。

審査基準の基準は恐らく流動的なもので、一概にこうすれば安全と言い切れるものだとは断言できませんが、 何らかのプラスアルファの機能実装は必要になるだろうというのが私の見解です。