27 | 10月 | 2011 | HMDT Blog

カテゴリー : 2011年 10月27日

iOSデバイスの機能をUIRequiredDeviceCapabilitiesを使って調査


iOSアプリでは、アプリの情報をInfo.plistというファイルに記述する。ここにはいろんな情報を書けるんだけど、その中に「どのデバイスでこのアプリが使用可能か?」ということを表すものがある。UIRequiredDeviceCapabilitiesというキーに指定する。

ここでの指定は、デバイスのモデル名を直接書くのではなく、どんな能力を持つデバイスをサポートするか、ということを使う。たとえば、電話機能があるとか、カメラがあるとか、GPSがあるとか、っていう感じのやつがある。指定できるキーの一覧は、”Information Property List Key Reference“で定義されている。

ということでデバイスモデル名からは独立した形で指定するんだけど、とはいっても実際にどのデバイスにインストール可能なのか知りたいよねぇ。ということで、調べてみた。手持ちのデバイスをつないで、UIRequiredDeviceCapabilitiesの値を設定してインストールできるかどうか実験した。

iPhone 4 (5.0) iPhone 3GS (5.0) iPhone 3G (4.2.1) iPod touch 4th (5.0) iPod touch 3rd (5.0) iPod touch 2nd (4.2.1) iPad 2 3G (5.0) iPad 2 WiFi (5.0) iPad WiFi (5.0)
telephony
wifi
sms
still-camera
auto-focus-camera
front-facing-camera
camera-flash
video-camera
accelerometer
gyroscope
location-services
gps
magnetometer
gamekit
microphone
opengles-1
opengles-2
armv6
armv7
peer-peer
bluetooth-le

こんな感じ。iPhone 4SとiPod touch 5thは、まだ入手していないので実験できなかった。iPod touch 1stは、iOS 3.0をビルドできる環境がなかったのでこれも実験できず。

この表を漫然と見ても、直感的に分かりにくいよね。ということで、これをベン図にしてみた。こんな感じ。

どうよ?少しは分かりやすくなったかな。

作ってて思ったのは、iPhoneの世代とiPod touchの世代は、微妙にかみ合っていないこと。iPod touchはiPhoneの機能を少し遅れくらいでとりこんでいる。

あと、iPhone 3Gはgamekitに対応していないのがちょっと意外だった。iPod touch 2ndは対応しているのに。これは、Bluetoothを持っているかいないかというのが効いているんだと思う。Bluetoothがないとpeer-peerができないので。

iPadはWiFiモデルでもmagnetometerを持っているのもちょっと驚きだった。GPSなしだとちょっと無駄な気もするのだが。

この図を見ていると、iOSデバイスがどういう風にハードウェアを拡張してきたかが分かるね。

追記:コメントの方で、iTunes Connect Developer GuideのAppendixに載っている、っていう情報をいただきました。ありがとうございます。そんなところにあったとは気づかなかったすよ。

iOS 5でviewWillAppear:がaddSubview:しただけで呼ばれる


iOSアプリで、起動時処理の定型に、UIViewControllerのインスタンスを作成してウインドウにaddSubview:する、というものがある。iOS 4までは、これだとUIViewControllerのviewWillAppear:とかが呼ばれないので、自前で呼ぶというのが必要だった。

// Add controller
[_window addSubview:_viewController.view];

// Call viewWillAppear: and viewDidAppear:
[_viewController viewWillAppear:NO];
[_viewController viewDidAppear:NO];

んが、iOS 5になったら、addSubview:するだけでviewWillController:とかが呼ばれるようになってしまった。ある意味ありがたい。だけど、iOS 4とiOS 5の両方で動かそうとすると、問題が発生する。iOS 5だとviewWillAppear:が連続して2回呼ばれてしまうのだ。ある意味ありがた迷惑である。

となると、実行時にOSのバージョン調べて呼び分けるしかねーな。たとえば、iOS 5から追加されたメソッドを使って、判定する事ができる。

// Add controller
[_window addSubview:_viewController.view];

// For prior to 5.0
if (![_viewController respondsToSelector:@selector(willMoveToParentViewController:)]) {
    // Call viewWillAppear: and viewDidAppear:
    [_viewController viewWillAppear:NO];
    [_viewController viewDidAppear:NO];
}

これで期待通りの動きになる。ま、viewWillAppear:を2回連続で呼ばれても問題ないようにするべきなのかもしれんが、それはそれでいろいろあるし。

iOS 5専用にしちまえば問題はなくなるんだけど、現実問題そうもいかん。Appleの前バージョン切り捨ては容赦ないな。