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

SysStats Monitor iOS6/iPhone5 (Retina 4) 対応のまとめ

現在、SysStats MonitorをiOS6/iPhone5 (Retina 4) 対応にするための改修を、コツコツとやっています。iOS6がリリースされてから2ヶ月ほど経つので、あまり新鮮な情報ではないですが、その作業が概ね完了したので、一通りやったことをまとめてみました。

大きく分けると、以下の3項目になります。

iPhone5 (Retina4) への対応

こちらは、見た目の調整であり、以下の2点が大きな目的となります。

  • Retina4ディスプレイのサイズに合わせること
  • 旧機種では、今まで通り表示されること

実際には、単純に画面の縦幅を延ばせばいいというわけではなく、操作に関する問題もいくつか出ました。

画面サイズの変更

640 x 1136 pixelsのLaunch Imageを作成して、プロジェクトに追加することで、画面サイズが変更されます。

Main Interfaceに設定されているNIBの変更

Main Interfaceに設定されているNIBファイル(通常はMainWindow.xib)のWindowオブジェクトの"Full Screen at Launch"プロパティをONにする。
それをやらないと、UITabBarControllerを使っている場合、tab barが反応しなくなってしまうようです。
ios - UITabBarController does not respond on iPhone 5 simulator: 4-inch retina display - Stack Overflow

Autosizing Maskの調整

iPhoneiPadの両方にユニバーサルバイナリ方式で対応しているアプリの場合は、すでに正しく設定されていることと思いますが、SysStats Monitorの場合、UIを共通化していなかったので、iPhone用のUIには、自動的にリサイズされるような設定はしていませんでした。
いくつかの画面で、表示が上の方に偏ったり、重なってしまったりしたものがあったので、正しく表示されるよう調整しました。

UIActionSheetの調整

ここまでの対応をしたところ、画面の見た目上は、正しく表示されるようになりましたが、UIActionSheetについては、2つの問題が発生しました。

  • iPhone5だと、一番下のボタンが反応しない。
  • 旧機種だと、一番下のボタンが表示されない。

UIActionSheetを表示させるメソッドがいくつか提供されており、これまでは、tab barから出したり、現在のviewから出したりで、統一できていませんでした。今回は、すべてを以下のメソッドに置換えることで解消されました。

[actionSheet showInView:self.view.window];

同時に、"Presenting action sheet clipped by its superview"というワーニングも出なくなりました。

参考: Objective-Cと戦うブログ: UIActionSheetで「Presenting action sheet clipped by its superview.」というエラーについて

iOS6への対応

SDKの対応アーキテクチャの変更

最新のXcodeでは、armv6(iPhone 3G)と、iOS 4.3よりも前のOS向けのバイナリの生成が出来なくなっています。
Xcode Release Notes
これにより、私の所有している環境では、iOS5.1以降のみ実機テストが可能な状態になってしまいました。
そのため、以下の対応を行いました。

  • Architectures: armv7, armv7sに変更し、armv6を削除
  • iOS Deployment Target: iOS5.1
デバイスの回転への対応

iOS6から、デバイスが回転したときのイベントのハンドリング方法が変わりました。
UIViewControllerのデフォルトの実装では、全方向の回転を受付けるのがデフォルトになっているようです。
SysStats Monitorの場合、iPad版はそれで問題ないのですが、iPhone版はデバイスの回転をサポートしていません。
それを抑止するため、iPhone版のApplicationDelegateクラスに、以下のメソッドを追加しました。

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    return UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown;
}

尚、起動時のRootViewControllerの登録を、古い方法で記述していると、iOS6では回転したときのイベントが発生しなくなってしまうようです。
iphone - iOS 6 shouldAutorotate: is NOT being called - Stack Overflow

iOS5でやり残していたものへの対応

UDIDを取得するメソッドがdeprecatedになった

iOS5で、すでにUIDevice.uniqueIdentifierプロパティは、deprecatedになっていましたが、対応が漏れていました。
将来的に削除されたときに備えて、以下のようにプロパティの存在チェックをしてから呼び出すように変更しました。

    // prepared for that uniqueIdentifier is deprecated.
    uniqueIdentifierLabel.text = [currentDevice respondsToSelector:@selector(uniqueIdentifier)] ? currentDevice.uniqueIdentifier : @"N/A";