エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

SwiftでWebViewアプリ

きっかけ

Swiftでいろいろアプリを作っているが、なかなか言語が覚えられない。
ネイティブ系のエンジニアではないからかもしれない。
WebViewを使えば、楽できるのではないかと思い、実施に至る。

環境情報

$> SW_VERS
ProductName:    Mac OS X
ProductVersion: 10.12.3
BuildVersion:   16D32

$> swift -v
Apple Swift version 3.1 (swiftlang-802.0.48 clang-802.0.38)

$> xcodebuild -version
Xcode 8.3
Build version 8E162
igarashitoshio-no-MacBoo

Xcodeのバージョンによっては、実施方法に差が出るので、一応載せとく。

やり方

プロジェクト作成

兎にも角にもプロジェクト作成が最初の仕事。

  1. Xcodeを起動して、Create a new Xcode projectを選択。
  2. Single View Applicationを選択してNext
  3. Languageをswiftにして、後はテキトーに入力
  4. 保存するディレクトリを選んでcreate

StoryBordの削除

SwiftはStorybordを使って、部品の配置を決める。
しかし、WebViewは部品一つしか必要ないので、あっても意味が無いので削除する。
※とくに削除しなくても問題ないので、飛ばしてもいいかも?

  1. Xcodeのサイドバーの"Show the Project navigator"を表示
  2. 一番トップにある、プロジェクト名のファイルを選択
  3. General > Develop Info > Main Interface の内容を空にする
    こいつで参照するStorybordを決めている。
  4. Main.storyboardを削除

ViewController呼び出し

storybordを削除したので、自前で呼び出す処理が必要らしい。
AppDelegate.swiftファイルを下記の通り編集する。
※コードは一部抜粋

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var navigationController: UINavigationController?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        window = UIWindow(frame: UIScreen.main.bounds)
        
        let viewController: ViewController = ViewController()
        window!.rootViewController = UINavigationController(rootViewController: viewController)
        window!.makeKeyAndVisible()
        return true
    }

やっていることメモ

  1. ベースとなるウィンドウのインスタンスを生成。
  2. ベースとなるViewControllerを生成。
  3. 1.で作成したwindowの一番上位のViewConntrollerにUINavigationControllerを指定。
    さらに、そのUINavigationControllerの一番上位のViewConntrollerに、2.で作成したviewControllerを指定
  4. 1.で作成したwindowを有効化

WebViewを全画面表示

import UIKit

import WebKit

class ViewController: UIViewController, WKNavigationDelegate {

    let webview: WKWebView = WKWebView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        webview.frame = view.bounds
        webview.navigationDelegate = self
        view.addSubview(webview)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

viewにwebviewのインスタンスを生成したものを埋め込む。
やる際は、WebKitのインポートをお忘れなく!
なんでビルドエラーになるのか分からず、1時間くらい時間を浪費するハメになった。。。

完成

上記をやれば、とりあえず実行するとwebviewが全画面で表示される。
ただし、真っ白だけど。。。

htmlを表示してみる

やりたいのは、ローカル保持しているHTML表示
外部のモノを参照することもあるだろうけど、やりたきことは別なので、やってみる。

配置場所の作成

まずは、htmlを配置する場所を作る。
Resourcesにhtmlなどを置こうと思う。
Xcodeだと、ディレクトリとは呼ばずにGroupと呼ぶらしい。
なぜだかは知らないけど、かなり迷う。
File > New > Group を選択して、Resourcesを作成

HTML作成

作ったResources内に、index.htmlを作成する。
File > New > Fileから、htmlファイルを作る(emptyを選んでindex.htmlという名でファイルを作る)
作ったら、ファイルを以下の内容にする。
今回は表示させたいだけなので、別になんでもいい。

<html>
<head>
</head>
<body>
test
</body>
</html>

htmlファイルのロード

作ったindex.htmlをwebviewに読み込ませる。

import UIKit

import WebKit

class ViewController: UIViewController, WKNavigationDelegate {

    let webview: WKWebView = WKWebView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        webview.frame = view.bounds
        webview.navigationDelegate = self
        view.addSubview(webview)
        
        let url = Bundle.main.url(forResource: "index", withExtension: ".html")!
        let request = URLRequest(url: url)
        webview.load(request)
        
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

実行

実行すると、index.htmlの内容が出力されるはず。

感想

htmlの表示ができたので、あとはWebの知識とJS・CSSの考えを流用すれば行けるハズ。
デフォルトOptionalが有効なのが、違和感ありすぎて辛い。。。

特に、xcodeが全て英語なので、英語に慣れてないと拒絶反応が出る。
あと、デリゲートって何?おいしいの?
デリゲートの意味が未だに理解できない。
調べはするが、それってinterfaceとか使って呼び出すメソッドを決めておき、処理は宣言しているところで書くのと同じなんじゃ。。。って思う。
これは、いわゆるFacadeなのだろうか?
いままでプログラミングしてきて思うに、Facade使って上手くいったパターンがほぼないのだが、検討違いだろうか?
愚痴っぽくなってしまったので、ここでおしまい。

WebViewを使ったアプリには、可能性を感じる。
ネイティブ側の問題が発生すると死にそうだけどね。。。

参考サイト

iOSでガワネイティブ - Qiita

swift - How to add a navigation bar to WKWebView? - Stack Overflow

SwiftでWKWebViewを使ってみた - Qiita