読者です 読者をやめる 読者になる 読者になる

あおみかんのブログ

フリーランスのIT系エンジニア。ゲーム制作スタジオ4th cluster代表。

僕がiOS6対応アプリをiOS7対応にするためにやったいくつかのこと

iOS7がリリースされて「うちのアプリもiOS7とやらに対応しなきゃならんのかね?」などと上司が言ってきたとか、It's cool. だからさっさと対応したいとか、事情は色々あると思いますが、iOS7に対応するための方法をメモしておきます。

読者とアプリの前提条件

  • iOSアプリが書けること
  • iOS6以上専用アプリであること *1
  • XCode5が入っていること
  • まだiOS7対応がよくわかっていないこと
    • 分かってるならこんな記事を読む必要はない

iOS7になって変化したこと

「対応するために何をしなきゃいけないのか」を理解する上で、まずはiOS7になって何が変わったのかを理解する必要があります。

ステータスバーがビューの上に表示されるようになった

iOS6

f:id:akn_ep:20130924022809p:plain

iOS7

f:id:akn_ep:20130924022824p:plain

特にナビゲーションバーがある場合は、ステータスバーと統合された様に見えますね。
ナビゲーションバーも一緒に、ビューの上に被るように表示されています。

ナビゲーションバーがない場合は、そのままビューの上に表示されるので、中のコンテンツに合わせて白い表示と黒い表示を切り替える必要が出てきます。

ビューのサイズが変わった

具体的なサイズはどっかに載ってると思うので割愛しますが、ステータスバーやナビゲーションバーの変更もあって、様々なビューの基本的なサイズが変わったみたいです。

具体的にやるべきこと

Storyboardの基本設定

とりあえず以下の画像と同じ設定にしておけばOKです。

f:id:akn_ep:20130924024048p:plain

Global Tint の設定

アプリケーションのカラーイメージにあわせて、"Global Tint" も設定しておくと良いです。

ナビゲーションバーの色

NavigationController の Simulated Metrics で Top Bar の色を適宜変えると良いです。
また、基本的にNavigationController以外ではInferredにしておくと良いでしょう。

ステータスバーの色

UIViewControllerのメソッド "(void)setNeedsStatusBarAppearanceUpdate" や "(UIStatusBarStyle)preferredStatusBarStyle" を利用します。
これでスクロール中、ある時点で背景が黒くなるような場合にも対応できます。

UIViewController ごとの設定

恐らくほとんどのビューコントローラーでは、ナビゲーションバーの下にビューが潜り込んでしまうと(上記の例のように)困ってしまうので、
以下のようにExtend Edges→Under Top Barsのチェックを外してしまいましょう。

f:id:akn_ep:20130924031114p:plain

ただし、単一のTableViewやScrollVIewの場合はこの限りではないので、余計かことをせずにそっとしておくと良いです。
半透明のナビゲーションバーが綺麗に描画され、オフセットもうまい具合に処理されるはずです。

AutoLayoutへの対応

さて、これが今回のメインですね。

基本的な作業手順は以下の通りです。

  1. 乱れたビューを手作業できちんと再配置する
  2. 大まかな制約を手動で定義する(*後述)
  3. "Add Missing Constraints in ViewController" をやる
  4. 4インチに拡大、iOS6版の表示を試す*2、横にしてみる(アプリで横になる事があるなら)
    1. 上手くいかない時は Cmd+Z で戻してConstraintsを追加してみましょう。 どうしても上手くいかない時は一回 "Clear Constraints in ViewController" して1から頑張りましょう。
「大まかな制約を手動で定義する」コツ

AutoLayoutをする時、ここのコツで作業の効率が変わる、気がします。

まず、UIViewを利用してビューの階層構造を適切に作っておきましょう。 1階層にビューが並びまくってるのはちょっとまずいです。 2階層ぐらいが調度良いと思いますが、ビューの複雑さ次第ではもう少し深いケースもあるでしょう。

(悪い例)

f:id:akn_ep:20130924030145p:plain

(良い例)

f:id:akn_ep:20130924030152p:plain

こんな感じに直したら、あとは以下のヒントを参考に、Constraintsを荒く定義します。

  • 縦に伸びるビューは、上と下をチェックして"Add Constraints"する。 height は追加しない。
    • 横も同様
  • 画面上部にあって横いっぱいに広がっているものは、上と左右をチェックして"Add Constraints" (widthはConstraintsにしない、必要に応じて下かheightを指定)

HTML/CSSが書ける人なら、ブロック要素に対応する形でUIViewの階層を定義し、それらのmargin設定に近い形でConstraintsの設定を行う、といった感覚でできると思います。

後からレイアウトを変更したいとき

変更したいビューを選択して、"Clear Constraints"しましょう。 終わったら上記の手順を踏めば完了です。 "Clear Constraints in ViewController" で全部リセットしてしまうと作業量が多くて大変なので注意しましょう。

プログラムからビューを弄りたい時

なるべくプログラムから描画したい領域にあわせてUIViewを定義しておいて、
そのサブビューになるように表示したらいいと思います。

もっと凝ったことをやりたい?公式ドキュメントを舐めるように読むしかないんじゃね?

蛇足

ちなみに、AutoLayoutは指定できるConstraintsの形式から、線形計画問題を解いてるのは明らかなので、その辺の知識があると少しだけ都合がいいかもしれません。 使うだけなら、あまり関係ないかもしれませんが。

ロジックの分岐

Prefix.pch に以下の記述をしておくと楽です。

#define IS_IOS6 (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1)

※ defineの内容はApple公式で推奨してるものです。


その他ハマったところ

  • ステータスバーの色が反映されない!?
    • JASidePanels などのContainerViewControllerを作るライブラリでバグが起きるようです。 必要に応じてContainerViewControllerになっている側でpreferredStatusBarStyleをオーバーライドして、メインの子ビューコントローラの preferredStatusBarStyle を呼んでやると良いと思います。

おわりに

半分以上がAutoLayoutの解説になってしまいました。 まぁ、意外と互換性があるので、UI以外は共通で行けちゃいます。
今回は言及しませんでしたが(というか僕が使ってないので言及できませんでしたが)画像をデバイスやOS毎に柔軟に切り替えるための、Asset Catalogという機能が追加されたみたいなので、必要に感じる人はこれを使うと良いかもしれません。

*1:きょうびiOS5系にも対応しようとか、まぁいい加減やめたほうが良いんじゃないでしょうか。 まぁ、StoryBoardを分割して、IBOutlet,IBActionの辻褄が合うようにすれば可能な気がしますけど。工数は数倍になるんじゃないですかね。

*2: 先のView As で iOS 6.1 or Earlier を選ぶ