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

#スプラッシュとは

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

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

## 参考：個人アプリ「バーベリー」 
![s_IMG_0186.PNG](https://qiita-image-store.s3.amazonaws.com/0/111366/9cd2d27a-dcfb-6d44-264d-bafb84aacf0f.png)

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

# スプラッシュ画面の役割

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

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

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

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

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

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

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

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

#設定ファイルと実装方法

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

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

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

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111366/6818158e-dd9b-d6e6-91e4-043572b27279.png)


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

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

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

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

![s_スクリーンショット 2016-12-09 19.24.27.png](https://qiita-image-store.s3.amazonaws.com/0/111366/5e64d37d-1ea9-8e82-4b0f-272ada14199a.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.5`と`Retina HD4.7`に該当の解像度の画像を設定すれば問題ありませんが、もし以下のようにRetinaの画像をセットしなかった場合、

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111366/ccccc4dc-aeb4-189a-7976-ffcb6f7e23c7.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](https://qiita-image-store.s3.amazonaws.com/0/111366/f4e52a18-741e-3ee6-95da-5e19425e8dc3.png)

<img width="1017" alt="スクリーンショット 2016-12-12 19.16.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/8a427410-c3bf-c93b-03a3-909c6ae55a90.png">

参考リンク(xcode6)
http://dev.classmethod.jp/references/ios8-launch-screen-xib/

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

<img width="537" alt="スクリーンショット 2016-12-12 19.10.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/9ab9a51d-8984-fde7-1070-45b951666219.png">

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

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

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

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

こんな感じで設定しようとすると
<img width="268" alt="スクリーンショット 2016-12-12 19.07.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/e0c461af-7880-d169-5b85-e913d07352a3.png">

違法だよ！って言われます。
<img width="259" alt="スクリーンショット 2016-12-12 19.07.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/2d48911f-3a44-06e8-1534-28f0e56aeb9a.png">

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

## ③SplashViewController

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

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

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

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

![スクリーンショット 2016-12-12 19.30.05.png](https://qiita-image-store.s3.amazonaws.com/0/111366/0c7157fe-6f54-10f2-429b-2eb6701f0bf5.png)


SplashViewControllerの役割としては

* 起動画面でアニメーションさせる
* 起動後の遷移画面を制御する

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

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

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

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

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

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

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

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

### ライフサイクル（viewDidAppear）

```swift
override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.chooseShouldLaunchViewController()
    }
```
Viewが表示された後に遷移先を制御するメソッドを呼び出しています。

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

```swift
/**
     起動すべきViewControllerを起動する。
     */
    fileprivate func chooseShouldLaunchViewController() {
        if UserDefaults.standard.shouldDisplayTutorial() {
            // 初回起動
            launchTutorial()
        } else {
            // ２回目以降
            launchHome()
        }
    }
```

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

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


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

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

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

`AppDelegate`の`application(_:didFinishLaunchingWithOptions:)`にて

```swift
var storyboardName: String

if UserDefaults.standard.shouldDisplayTutorial() {
    // 初回起動
    storyboardName = "Tutorial"
} else {
    // ２回目以降
    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を指定すると２つ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が最初に表示されるのかは、意外にハマりました。スプラッシュ画面に時間をかけるべきではないので、この記事が助けになったら嬉しいです！