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

24/7 twenty-four seven

iOS/OS X application programing topics.

iOS 4.0 と iPhone OS 3.x の両方で動作するアプリケーションをビルドする設定

iPad Xcode Objective-C Cocoa iPhone

ベース SDK と Deployment Target を設定する

ベース SDK を iPhone デバイス 4.0 にします (iPad の場合は 3.2)。


iPhone OS Deployment Target をサポートする OS の最も低いバージョンにします。
(下の場合は iPhone 3.0 以降で動作する。)


ベース SDK を下げるという方法もありますが(iPhone SDK では 3.2 以降の SDK しか同梱されないので無理ですが)、iPhone アプリケーションの場合、最新の SDK でビルドする方がなにかと安定します。
ですので特別に理由がない限り、リリースされている最新の SDK でビルドして、Deployment Target を下げる、ということを原則的に行なったほうがいいです。
これは今後マイナーバージョンアップがあった場合などでも同様です。
例えばこれまでなら、iPhone の場合は 3.1.3 でビルドして、Deployment Target を 3.0 あるいは 2.2.1 にするというのが効果的でした。
ビルドは最新、 Deployment Target は普及してる OS に合わせるようにするのがいいでしょう。


上記の設定では「すべての構成」に対して行っているかどうか注意しましょう。
デバッグ構成にのみ適用して、リリースしたものの Deployment Target が 4.0 とかだと悲しいことになります。

新しい Framework を Weak Link に設定する

古い環境には含まれていない Framework をリンクしていると、Dynamic Linker がシンボルのロードに失敗してアプリケーションが起動しません。

dyld: Library not loaded: /System/Library/Frameworks/iAd.framework/iAd
  Referenced from: /var/mobile/Applications/71E4CD8F-4E9E-4FC1-A7B9-6AE975E9C2B0/Test.app/Test
  Reason: image not found


その場合は、新しい OS にのみ存在する Framework を Weak Link に設定します(今回は iAD.framework)。


「ターゲット」>「実行ファイル」の左の三角を順に開き、「バイナリをライブラリにリンク」を選択します。
上部のペインにリンクしているフレームワークが表示されるので、「役割」のカラムをクリックして、 Required > Weak に変更します。

必要なら、OS のバージョンごとに処理を分岐する

古い API には存在しないセレクタを呼び出したりすると、クラッシュしますので必要に応じて処理を分岐します。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 4.0) {
        bannerView = [[ADBannerView alloc] init];
        bannerView.delegate = self;
        [self.view addSubview:bannerView];
    }

分岐の判断条件としては、上記の systemVersion を見る方法の他に、新しい API にしか存在しないクラスがあるかどうかを見る方法や、

Class clazz = NSClassFromString(@"ADBannerView");
if (clazz) {
    bannerView = [[ADBannerView alloc] init];
    bannerView.delegate = self;
    [self.view addSubview:bannerView];
}

新しい API にしか存在しない関数のポインタが NULL かどうかなどがあります。

if (UIGraphicsBeginImageContextWithOptions != NULL) {
    bannerView = [[ADBannerView alloc] init];
    bannerView.delegate = self;
    [self.view addSubview:bannerView];
}

サンプルコード

iPhone OS 2.x と 3.x のころのものですが、 アップルのサンプルで MailComposer というものが新しい機能を使いつつ、古い環境でも動作させるアプリケーションのサンプルです。
こちらも参考にしてみてください。