きっかけ
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のバージョンによっては、実施方法に差が出るので、一応載せとく。
やり方
プロジェクト作成
兎にも角にもプロジェクト作成が最初の仕事。
- Xcodeを起動して、Create a new Xcode projectを選択。
- Single View Applicationを選択してNext
- Languageをswiftにして、後はテキトーに入力
- 保存するディレクトリを選んでcreate
StoryBordの削除
SwiftはStorybordを使って、部品の配置を決める。
しかし、WebViewは部品一つしか必要ないので、あっても意味が無いので削除する。
※とくに削除しなくても問題ないので、飛ばしてもいいかも?
- Xcodeのサイドバーの"Show the Project navigator"を表示
- 一番トップにある、プロジェクト名のファイルを選択
- General > Develop Info > Main Interface の内容を空にする
こいつで参照するStorybordを決めている。 - 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 }
やっていることメモ
- ベースとなるウィンドウのインスタンスを生成。
- ベースとなるViewControllerを生成。
- 1.で作成したwindowの一番上位のViewConntrollerにUINavigationControllerを指定。
さらに、そのUINavigationControllerの一番上位のViewConntrollerに、2.で作成したviewControllerを指定 - 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を使ったアプリには、可能性を感じる。
ネイティブ側の問題が発生すると死にそうだけどね。。。
参考サイト
swift - How to add a navigation bar to WKWebView? - Stack Overflow