Edited at
SwiftDay 10

iOSのスプラッシュ画面実装における注意点と実装方法


スプラッシュとは

僕もアプリ開発に携わるまでは、それをスプラッシュと呼ぶとは知りませんでした。

スプラッシュ画面とは、ネイティヴアプリを開いたときに一番最初に出てくるロゴマークとか出てくる、あの画面です。


参考:個人アプリ「バーベリー」

s_IMG_0186.PNG

スプラッシュに関するドキュメントが全てまとまっているものが見つからなく、実装時にいろんなところを参照したので、僕がハマったところなんかも含めてまとめたいと思います。


スプラッシュ画面の役割


スプラッシュはアプリのブランディングに重要

iOSアプリを作るにあたってスプラッシュ画面の作成は避けては通れません。

なぜならば、スプラッシュはアプリを開くたびに毎回ユーザーの目に入るアプリの顔であるからです。

ブランディングに貢献するのです。


諸々の処理をすることが多い

スプラッシュはただの静的な画像だけのこともありますが、例えばTwitterのようにアニメーションをしたり、iPadでは違うものを出したりと、UIの工夫をする場合は意外に手間がかかったりします。

また、多くのアプリは、初回起動ではチュートリアルを出し、二回目以降はトップに遷移するなどの起動時の条件分岐をしています。

で、その条件分岐をスプラッシュ画面のViewControllerを用意して、SplashViewControllerとする場合が多いのです。


設定ファイルと実装方法

スプラッシュ画面の実装にあたっては、以下の3人の登場人物がいます。スプラッシュ三銃士と呼ばれています。(嘘

先に述べた目的によっては使わなくて済むものもあります。


①Images.xcasssetsのLaunchImageで設定する方法

1.png

画像ファイルを解像度別に設定できるImages.xcasssetsにて、LaunchImageにスプラッシュ画像を設定する方法があります。

Illustolatorとか得意な場合は、画面解像度別にファイルを作って、ここにはめていく方法も採用できるでしょう。作るのが面倒くさいけど。

ここで設定した画像ファイルは、LaunchScreen.xibLaunchScreen.storyboardを使わない場合にのみスプラッシュとして反映されます。

っていうのはつまり、以下のようにxcodeのプロジェクトのGeneralのApp Icon and Launch ImagesのLaunchScreenを空にするってことです。

s_スクリーンショット 2016-12-09 19.24.27.png

2019/08/30追記:iOS13からLaunchImageで設定する方法はiPadの分割機能を含めた全画面に対応できないことから使わない方が良さそうです(というか使ってはいけないかも)

参考リンク

http://makotton.com/2014/09/29/515

https://techracho.bpsinc.jp/yoshi-k/2019_08_28/79514


拡大モードに注意

ちなみに上記のLaunchImageのように、Retina HD5.5Retina HD4.7に該当の解像度の画像を設定すれば問題ありませんが、もし以下のようにRetinaの画像をセットしなかった場合、

2.png

アプリが全て拡大モードになります。iPhone6(7)やiPhone6(7)Plusでも、iPhone5Sと同じ解像度で表示されるのです。

解像度別に素材を作るのが面倒くさいときにあえてこのモードを使う場合がありますが、ぼやけるので極力使わない方がいいでしょう。

ちなみに僕の個人アプリのバーベリーでも、ver1.6.3現在、このやり方で拡大モードにしております。

参考リンク

http://qiita.com/uebo/items/854c284ed11aca741d93


②LaunchScreen.xibまたはLaunchScreen.storyboardで設定

xcode6までは、LaunchScreen.xibが、xcode7以降ではLaunchScreen.storyboardがプロジェクトを作った時にデフォルトで用意されます。

スクリーンショット 2016-12-12 18.54.05.png

スクリーンショット 2016-12-12 19.16.25.png

参考リンク(xcode6)

http://dev.classmethod.jp/references/ios8-launch-screen-xib/

多くの人がこれからアプリを作る場合、LaunchScreen.storyboardが生成されるかと思います。

スクリーンショット 2016-12-12 19.10.20.png

上のようにprojectのgeneralでLaunch Screen FileLaunchScreen.storyboardを入力すれば、このstoryboardが起動時に表示されるようになります。


LaunchScreen.storyboardのViewControllerはカスタムできない

このとき注意点があります。

このStoryboard上にあるViewControllerに、自分で作ったSplashViewControllerなりを指定しようとすると、エラーが出ます。

こんな感じで設定しようとすると

スクリーンショット 2016-12-12 19.07.53.png

違法だよ!って言われます。

スクリーンショット 2016-12-12 19.07.30.png

あくまでここでは、Viewしか設定できないようです。つまり、LaunchScreen.xibだろうがLaunchScreen.storyboardだろうが出来ることは全く一緒です。


③SplashViewController

最後の登場人物がSplashViewControllerです。

こいつは別に作らなくても大丈夫です。でも作ってる人が多いよ!っていうものですね。

アプリを開いて一番最初に開くViewControllerはprojectのgeneralのDeployment InfoのMain Interfaceにて設定します。

以下の場合は、自前で用意したSplash.storyboardを指定しています。

スクリーンショット 2016-12-12 19.30.05.png

SplashViewControllerの役割としては


  • 起動画面でアニメーションさせる

  • 起動後の遷移画面を制御する

大きくこの2つであることが多いと思います。


起動画面でアニメーションさせる

僕の個人アプリのバーベリーでは以下を参考にさせてもらっています。

http://qiita.com/osamu1203/items/a7c78666b18eb499c94b

この場合、起動後に最初に開くViewControllerをSplashViewControllerにする必要がありますね。

アニメーションのためのコードを書く必要がありますから。


起動後の遷移画面を制御する

例えば、私の現在勤めているJX通信社のNewsDigestでは(執筆当時)、SplashViewControllerを定義して以下のよう遷移画面を制御しています。


ライフサイクル(viewDidAppear)

override func viewDidAppear(_ animated: Bool) {

super.viewDidAppear(animated)
self.chooseShouldLaunchViewController()
}

Viewが表示された後に遷移先を制御するメソッドを呼び出しています。


遷移先を制御するメソッド

/**

起動すべきViewControllerを起動する。
*/

fileprivate func chooseShouldLaunchViewController() {
if UserDefaults.standard.shouldDisplayTutorial() {
// 初回起動
launchTutorial()
} else {
// 2回目以降
launchHome()
}
}

UserDefaultにフラグを保存しといてどう遷移するかを制御しています。

このほかにもログイン機能を持つアプリであれば、ログインしているか否かを判断して、ログイン画面に飛ばすかトップに飛ばすかを制御したりすることが多いと思います。


画面遷移の制御だけならSplashViewControllerは要らない?

@mono0926さんにコメントいただきました!

もし、ログイン未ログインの制御などをしたいだけであれば、SplashViewControllerを作る必要はありません。

AppDelegateapplication(_:didFinishLaunchingWithOptions:)にて

var storyboardName: String

if UserDefaults.standard.shouldDisplayTutorial() {
// 初回起動
storyboardName = "Tutorial"
} else {
// 2回目以降
storyboardName = "Main"
}
let storybord: UIStoryboard = UIStoryboard(name: storyboardName, bundle: nil)
window = UIWindow(frame: UIScreen.main.bounds)
window!.rootViewController = storybord.instantiateInitialViewController()
window!.makeKeyAndVisible()

みたいなかんじで書けば、画面制御のためにSplashViewControllerを作る必要はなさそうです。


注意点(追記)

Development Info(Info.plist)のMain Interfaceにも最初のstoryboardを指定して且つAppDelegateで初回のstoryboardを指定すると2つViewControllerが作られてしまうので注意が必要です。


UIMainStoryboardFile (String - iOS) Contains a string with the name of the app’s main storyboard file (minus the .storyboard extension). A storyboard file is an Interface Builder archive containing the app’s view controllers, the connections between those view controllers and their immediate views, and the segues between view controllers. When this key is present, the main storyboard file is loaded automatically at launch time and its initial view controller installed in the app’s window. https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW10



まとめ

以上、Splashについてまとめました。

どこをどう設定したらどのViewが最初に表示されるのかは、意外にハマりました。スプラッシュ画面に時間をかけるべきではないので、この記事が助けになったら嬉しいです!