iOS8対応時の注意点まとめ


アプリをiOS8に対応する際に確認しておく項目をまとめました。

## はじめに

iOS8対応とはざっくり言うとXcode6でアプリをビルドする事を差します。(厳密にはBaseSDK 8.0以上でビルドしたアプリ)
BaseSDKが上がる事により、既存のAPIがDeprecated(非推奨)になったり、新しいメソッドが追加されることによって今まで通りの実装では動作しなくなったり挙動が変わったりします。

本記事では上記によって実装に変更が入った部分や、アプリの運用上気をつけておく事について解説していきます。

> 言語はObjective-Cでの実装を解説します。Swiftでは言語仕様上、SDKとの連携などで不具合がある箇所が存在するため、別解説記事などと合わせて読んでいただく事をオススメします。

## 1.申請周り

先日、Appleは2015年2月1日より申請されるアプリについてiOS8と64bitアーキテクチャに対応する事を義務付けました。

* [64-bit and iOS 8 Requirements for New Apps - Apple Developer](https://developer.apple.com/news/?id=10202014a)

現段階ではXcode5.1.1(iOS7)以降なので、対応せずともアプリの申請は可能ですが、
早めに対応をしておいた方が良さそうです。
本章ではそれらの対応方法について解説します。

### 1.1 64bit(arm64)アーキテクチャ対応

iPhone 5Sで搭載されたApple A7プロセッサ(+ iOS7)から64bitでの動作をサポートしました。(それまでは32bitでの動作)
これによって、いままでよりも多くのデータや処理を扱う事ができるようになりました。
現状の各デバイスのスペックについては下記ページが参考になりました。

* [[iOS 8] iPhone/iPadスペック早見表（2014/9）- Developers.IO](http://dev.classmethod.jp/references/ios8-device-spec-list-2014-9/)

詳細についてはAppleから移行ガイドが配布されているのでそちらを参考にしてください。
本記事では64bitの要点のみを解説します。

* [Cocoa Touch 64ビット移行ガイド - Apple Developer](https://developer.apple.com/jp/devcenter/ios/library/documentation/CocoaTouch64BitGuide.pdf)

#### Valid Architecturesの設定

Valid Architecturesに`arm64`のアーキテクチャを追加します

![スクリーンショット 2014-11-19 16.07.56.png](https://qiita-image-store.s3.amazonaws.com/0/31823/92af6993-1500-dfbd-0ae6-1721288f7c20.png "スクリーンショット 2014-11-19 16.07.56.png")

場所 : projectファイル > Build Settings > Architectures > Valid Architectures

`${ARCHS_STANDARD}`とすでに登録されていればXcode6に最適化した際に自動で追加されているはずです。
以前は`${ARCHS_STANDARD_INCLUDING_64_BIT}`というのもありましたが、Xcode6ではどちらも同じアーキテクチャが指定されます。

Xcode6で新しくプロジェクトを作成した場合は`arm64`、`armv7`、`armv7s`がそれぞれ個別で登録されています。
`${ARCHS_STANDARD}`に`armv7s`が入っていないですが、必要であれば個別で登録します。

![スクリーンショット 2014-11-19 16.10.44.png](https://qiita-image-store.s3.amazonaws.com/0/31823/9846578e-ac99-5856-d805-3068ab929148.png "スクリーンショット 2014-11-19 16.10.44.png")

#### Build Errorへの対処

アプリ内部で使用している外部ライブラリが64bitに対応していない場合、Linker Errorなどが発生する場合があります。
その場合は各ライブラリを更新するなどの対処が必要ですが、サポートされていない場合もありますので注意が必要です。

#### Warningへの対処

64bit対応により整数型のバイト長が変わるため、実装によってはWarningがでます。

![スクリーンショット 2014-11-19 16.16.37.png](https://qiita-image-store.s3.amazonaws.com/0/31823/9164d7ee-1f05-215a-8ff6-05445a66a9b7.png "スクリーンショット 2014-11-19 16.16.37.png")
こんなのとか

![スクリーンショット 2014-11-19 16.20.20.png](https://qiita-image-store.s3.amazonaws.com/0/31823/306d4ebb-29cd-28eb-6770-2e363ad2cc0c.png "スクリーンショット 2014-11-19 16.20.20.png")
こんなのとか

対応方法については他の方々が詳しく解説されているのでここでは割愛します。

* [32bitと64bit、共通で使えるNSLogとかのフォーマット指定子 - Qiita](http://qiita.com/annaok/items/bf1c80184dac8a9945c2)
* [【iOS7】64ビット対応について調べてみた - Qiita](http://qiita.com/takabosoft/items/253cab6a7c2a8d8508ab)
* [iOSアプリ 64bit 対応メモ - Qiita](http://qiita.com/rayc5/items/95e238aa84415327be74)

### 1.2 iOS8ビルド

iOS8ビルドについてはXcode6でビルドすれば良いので、特に気にする必要はありません。
プロジェクト設定のBase SDKが8.0以上であればOKです。

![スクリーンショット 2014-11-19 16.33.17.png](https://qiita-image-store.s3.amazonaws.com/0/31823/749e9b60-5fe8-30fb-d9a5-b854d05a759b.png "スクリーンショット 2014-11-19 16.33.17.png")

ビルド時の注意箇所については2章にて詳しく解説します。

### 1.3 アプリバージョン

こちらは主にiTunes Connect周りでの注意事項ですが、申請方法の変更によりアプリバージョンとビルド番号の運用方法に気をつける必要があります。(特にVersionとBuildを同じ値で運用しているアプリ)

申請方法が変更になったことにより、リジェクトされたり、バイナリを差し戻したりして再度申請する時に同じBuildバージョンでの再提出ができなくなりました。
そのため、再提出にはBuildバージョンを上げたりするのが一般的ですが、VersionとBuildを同じ値で運用していると混乱しやすくなります。

* [【iOS】iTunesConnectリニューアル 個人的にわからなくなったポイント - Qiita](http://qiita.com/skatata/items/5f5f31dd564d08eed5e3)

![スクリーンショット 2014-11-19 16.44.25.png](https://qiita-image-store.s3.amazonaws.com/0/31823/92a8ffc4-fd62-4f2f-8727-11c8ab396e97.png "スクリーンショット 2014-11-19 16.44.25.png")

Version部分に対応するのが<font color ="red">`CFBundleShortVersion`</font>
Build部分に対応するのが<font color ="red">`CFBundleVersion`</font>です。

自分も最近まで勘違いしていたのですが、アプリバージョンを取得する方法を調べていると<font color ="red">`CFBundleVersion`</font>で取得している所が多いのですが、実際には<font color ="red">`CFBundleShortVersion`</font>を使うべきなんですね。

```objectivec:バージョン番号の取得
// Version
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];

// Build
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
```

運用としてはVersionには1.0.1などのこれまでの記載をして、build部分は1.0.1.1などとVersionの末尾にビルド番号を付与していく方法が良さそうです。

* [Information Property List Key Reference - Apple Developer](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html)
* [iOSアプリバージョンについて - Qiita](http://qiita.com/mo12ino/items/667f9f3fd3829440a20b)

## 2.iOS8

本章ではiOS8 SDKでビルドした際に旧SDKと影響が大きい部分についての解説をします。

### 2.1 Push Notification (プッシュ通知)

iOS8からプッシュ通知のデバイストークンの取得方法が変更になりました。
それにより正しい設定をしていないとプッシュ通知の登録ができません。

いままで使用していた`registerForRemoteNotificationTypes:`がDeprecatedとなり`registerUserNotificationSettings:`を使用するようになります。

詳しい設定方法については以前Qiitaに投稿したものがあるのでそちらを参考にしてください。

* [Xcode6でiOS8へPush通知が送れない場合の解決方法 - Qiita](http://qiita.com/peromasamune/items/90970e9f9d5c34d21cfd)

### 2.2 Local Notification (ローカル通知)

Push Notification同様にLocal NotificationにおいてもiOS8において仕様が変更になりました。
ローカル通知において、通知を表示するためにはユーザー認証が必要となり、通知を表示することをアプリ内で明記する必要があります。

ユーザー認証を行うにはiOS8から追加された`UIUserNotificationSettings`クラスで設定を登録します。
新しいクラスとなるため、旧バージョンのOSをサポートする場合は処理の分岐が必要となります。

```objectivec:サンプル
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    if (version_greater_than(@"8.0")) {
        UIUserNotificationType types =  UIUserNotificationTypeBadge|
                                        UIUserNotificationTypeSound|
                                        UIUserNotificationTypeAlert;

        UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];

        [application registerUserNotificationSettings:mySettings];
    }
}
```

* [[iOS 8] UILocalNotification もユーザー認証が必要になりました - Developers.IO](http://dev.classmethod.jp/references/ios-8-uilocalnotification-auth/)

### 2.3 Location (位置情報)

iOS8から位置情報の利用設定をユーザーが細かく制御できるようになり、ソースコード上での制御方法が変更になりました。
また、位置情報を取得する理由を明示することが必須になりました。

#### Authorization Status

これまで位置情報の認証ステータスは`[CLLocationManager authorizationStatus]`が`kCLAuthorizationStatusAuthorized`かそうでないかで判定していましたが、iOS8からDeprecatedになり、下記の認証ステータスが追加になりました。

* kCLAuthorizationStatusAuthorizedAlways
* kCLAuthorizationStatusAuthorizedWhenInUse

ただし、上記ステータスはiOS8から追加のためiOS7をサポートする場合はバージョンでの分岐が必要となります。

```objectivec:サンプル
-(BOOL)isLocationServiceAuthorized{

    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];

    if (version_greater_than_equals(@"8.0")) {
        if (status == kCLAuthorizationStatusAuthorizedWhenInUse || 
            status == kCLAuthorizationStatusAuthorizedAlways)
            return YES;
    }else{
        if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized)
            return YES;
    }

    return NO;
}
```

#### Info.plist

Info.plist内に位置情報を取得する理由を記述します。
常時許可と使用中のみ許可でそれぞれ用意します。
(初回利用時の確認ダイアログにこのメッセージが表示されます。)

![スクリーンショット 2014-11-19 17.55.49.png](https://qiita-image-store.s3.amazonaws.com/0/31823/97e10a21-3475-d071-8a8d-6164898eb7c7.png "スクリーンショット 2014-11-19 17.55.49.png")

* [iOS 8から位置情報を取得する方法が変わるよ - Qiita](http://qiita.com/koogawa/items/6ec24ca3201977e9642b)

## 3.Xcode6

Xcode6になってXcode5から動作が変わった部分(主にプロジェクト新規作成時)

### 3.1 LaunchScreen

iOS8から起動スクリーンにxibファイルを指定できるようになりました。

* [[iOS 8/Xcode 6] Launch Screen (スプラッシュ画面) を Interface Builder で作成できるようになりました - Developers.IO](http://dev.classmethod.jp/references/ios8-launch-screen-xib/)

ただし、iOS7以前のバージョンもサポートするアプリの場合、当然起動スクリーンにxibを指定する事ができないため表示がおかしくなります。
その場合、xibではなくAsset Catalogを指定します。(両方セットする事もできるみたいです。)

![スクリーンショット 2014-11-19 18.40.48.png](https://qiita-image-store.s3.amazonaws.com/0/31823/67128b65-567a-b80f-92d2-9f37739e4e78.png "スクリーンショット 2014-11-19 18.40.48.png")
こうなっているのを

![スクリーンショット 2014-11-19 18.40.37.png](https://qiita-image-store.s3.amazonaws.com/0/31823/fdba430d-c2cb-8232-5d59-c6592f236bd5.png "スクリーンショット 2014-11-19 18.40.37.png")
こうする

* [Xcode6でiOS7対応アプリを作るときのワナ - Dorapro エンジニアBLOG](http://www.dorapro.co.jp/engineerblog/?p=357)


### 3.2 Prefix Header

Xcode5以前ではプロジェクト作成時にPrefix Header(.pchファイル)が自動で追加されていましたが、Xcode6からは追加されなくなりました。

無くても困らないですが、下記の手順で手動追加ができます。

![スクリーンショット 2014-11-19 18.46.30.png](https://qiita-image-store.s3.amazonaws.com/0/31823/30f31095-6faf-5589-8de8-4a2a21f76b29.png "スクリーンショット 2014-11-19 18.46.30.png")
File > New > iOS > Other から`PCH File`を選択して作成

プロジェクト設定の`Prefix Header`に作成したヘッダーファイルのパスを登録します。
`$(SRCROOT)/$(PRODUCT_NAME)/PrefixHeader.pch`などとすると良いです。

* [Why isn't ProjectName-Prefix.pch created automatically in Xcode 6? - stackoverflow](http://stackoverflow.com/questions/24158648/why-isnt-projectname-prefix-pch-created-automatically-in-xcode-6)

### 3.3 その他

* [Xcode6とSwift&iOS8のアプリ開発で踏んだ地雷たち - Qiita](http://qiita.com/susieyy/items/019d5bc69f0921250437)

## 4.iPhone6,iPhone6 Plus

画面解像度をiPhone6,iPhone6 Plusに対応するにはそれらの画面サイズに対応する起動スクリーンを用意する事で対応できます。

主な方法は2つ

* __Launch Screen Fileの追加__
* __Launch Imageに4.7,5.5インチ画面用の起動画像を追加__

### Launch Screen Fileの追加

3.1であるようにxibを起動スクリーンに設定します。
これを指定するだけでXcodeはAuto Layoutに対応しているとみなされ、複数の画面サイズが有効になります。

### Launch Imageに4.7,5.5インチ画面用の起動画像を追加

Asset Catalogに4.7と5.5インチ画面用の起動画面を追加すると有効になります。

![スクリーンショット 2014-11-19 19.14.35.png](https://qiita-image-store.s3.amazonaws.com/0/31823/c572bca3-d58d-c623-081b-0dad019539af.png "スクリーンショット 2014-11-19 19.14.35.png")

`iOS 8.0 and Later`のチェックボックスにチェックを入れると`Retina HD 5.5`と`Retina HD 4.7`の起動画像を追加できるようになります。

* [iPhone6 4.7、5.5inch対応 メモ - Qiita](http://qiita.com/ux_design_tokyo/items/02d7010aaa47ea8ff292)
* [iPhone6/iPhone6 Plusの画面対応について - Qiita](http://qiita.com/uebo/items/854c284ed11aca741d93)

画面サイズ一覧

* [iPhone/iPad解像度早見表 - Qiita](http://qiita.com/tomohisaota/items/f8857d01f328e34fb551)

## tips

### 処理の分岐

本記事では処理の出し分けにOSバージョンを判定していますが、多用しすぎると実装上美しくないのと、今後どんどんバージョンが増えていくとカオスな事になりかねないので、クラスやメソッドの有無などで判定することをオススメします。

* メソッドが存在するかどうか: respondsToSelector:
* クラスが存在するかどうか: [Class class]

上記の2だけでも使えれば十分かと思います。

* [#8 「iOSのバージョン間の溝を埋めるテクニック」 tech.kayac.com Advent Calendar 2012Add Star - tech.kayac.com](http://tech.kayac.com/archive/8_ios_version.html)

## おわりに

64bit対応,iOS8対応,iPhone6(Plus)対応とやらなければならない事がたくさんありますが、ちょっとした見落としなどで大きな不具合につながってしまう恐れがあるので注意して開発を進めたいところです。

まだまだ他にもやるべき事がある気がしてますが、気づいたら追加していきます。

## 関連資料

* [iOS 8 for Developers - Apple Developer](https://developer.apple.com/jp/ios8/)
* [iOS Developer Library - Apple Developer](https://developer.apple.com/library/ios/navigation/)
* [iOS 8 特集 解説記事 170本 公開中!! - Developers.IO](http://dev.classmethod.jp/referencecat/ios8/)