きっかけ
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()
webview.frame = view.bounds
webview.navigationDelegate = self
view.addSubview(webview)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
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()
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()
}
}
実行
実行すると、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