Objective-Cのバージョン判定方法7選

Objective-Cのバージョンを判定する7つの方法を示す図解とサンプルコードObjctive-C

 

【当サイトはコードのコピペ・商用利用OKです】

このサービスはASPや、個別のマーチャント(企業)による協力の下、運営されています。

記事内のコードは基本的に動きますが、稀に動かないことや、読者のミスで動かない時がありますので、お問い合わせいただければ個別に対応いたします。

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10000時間以上』を満たすプログラマ集団によって監修されています。

はじめに

Objective-Cのバージョン判定は、アプリケーション開発において必要不可欠なスキルです。

特に複数のバージョンのiOSをサポートするアプリケーションを開発する際には、実行しているシステムのバージョンに応じて異なるコードを実行することが求められます。

この記事では、Objective-Cのバージョン判定方法を7つ紹介し、実際のコード例とともにその使い方や注意点を詳細に解説します。

この記事を読むことで、Objective-Cのバージョン判定に関する知識を深めることができ、あなたのアプリケーションをより洗練されたものにすることができるようになります。

●Objective-Cのバージョン判定の基本

Objective-Cは、AppleのiOSおよびmacOSの開発で広く使用されているプログラミング言語です。

Objective-Cにおけるバージョン判定は、主にAPIの可用性を確認するために使用されます。

開発者は、利用可能なAPIがバージョンごとに異なる可能性があるため、コードが特定のバージョンのOSで正しく実行されることを保証するためにバージョン判定を行う必要があります。

APIが存在しない古いバージョンのOSで新しい機能を使おうとすると、アプリケーションはクラッシュする恐れがあります。

そのため、安全に機能を実装するためには、実行時にOSのバージョンを確認し、条件に応じたコードを実行することが重要です。

○Objective-Cとは

Objective-Cは、C言語にオブジェクト指向の概念を導入した言語で、Appleのソフトウェア開発に長年にわたって使われてきました。

Objective-Cは、Smalltalkのメッセージング機能をC言語に組み合わせることにより、開発者がより抽象的かつ再利用可能なコードを書くことを可能にします。

○バージョン判定の必要性

iOSやmacOSなどのアップデートには新しい機能が追加される一方で、古い機能が非推奨になったり削除されることもあります。

アプリケーションが複数のバージョンのOSで動作するようにするためには、実行中のOSのバージョンをチェックし、対応するコードを用意する必要があります。

これは、ユーザーにとって最良の体験を提供し、アプリケーションのクラッシュを防ぐためにも不可欠です。

バージョン判定を適切に行うことで、アプリケーションはさまざまなユーザー環境で安定して機能し、開発者は保守管理の手間を減らすことができます。

●Objective-Cのバージョン判定方法

Objective-Cでアプリケーションを開発する際、異なるバージョンのiOSやmacOSに適切に対応するためには、そのバージョンを判定し、条件に応じて異なる処理を行うことがしばしば必要です。

例えば、新しいバージョンのOSに追加されたAPIを使用している場合、古いバージョンのOS上でそのAPIが存在しないためにエラーが発生する可能性があります。

このような問題を避けるため、Objective-Cではプリプロセッサ指令やランタイム機能を使用してOSのバージョンを判定するいくつかの方法が存在します。

これらの方法を適切に使用することで、アプリケーションの互換性を保ちつつ、新機能を活用することができます。

○バージョン判定方法1:コンパイラディレクティブを使用する

Objective-Cでは、#if, #else, #endif といったプリプロセッサ指令を用いて、コンパイル時に特定の条件が満たされているかを判定することができます。

例えば、特定のOSバージョンでのみ利用可能なコードブロックを条件付きでコンパイルする際に使用します。

// iOSバージョンが9.0以上でのみコンパイルされるブロック
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000
    // iOS 9.0以上で利用可能なコードを記述
#endif

このコードでは、__IPHONE_OS_VERSION_MAX_ALLOWED というマクロを使用して、コンパイルされているiOS SDKのバージョンを判定しています。

このマクロは、現在使用されているSDKの最大バージョンを表しており、この数値を基に条件分岐を行うことで、SDKのバージョンに応じたコードを記述することが可能です。

○バージョン判定方法2:Foundationフレームワークのチェック

Objective-CのFoundationフレームワークには、OSのバージョンを判定するためのいくつかの便利な関数が含まれています。

NSFoundationVersionNumber はその一つで、実行時にOSのバージョンをチェックする際に使用します。

下記のコード例では、NSFoundationVersionNumber を使用してバージョン判定を行っています。

// 実行時にiOSのバージョンがiOS 10.0以上であるかを判定する
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_9_x_Max) {
    // iOS 10.0以上でのみ必要な処理を記述
}

このコードでは、NSFoundationVersionNumber_iOS_9_x_Max という定数と NSFoundationVersionNumber の値を比較しています。

これにより、iOS 10.0以上でのみ実行されるコードブロックを作成することができます。

○バージョン判定方法3:システムバージョンの比較

Objective-Cでのバージョン判定には、実行しているデバイスのシステムバージョンを直接比較する方法があります。

これは、UIDeviceクラスのsystemVersionプロパティを使用して、現在のOSのバージョンを取得し、それを目的のバージョンと比較することで行います。

下記のコードは、デバイスのシステムバージョンを取得し、それがiOS 10.0以上であるかどうかを判定する方法を表しています。

NSString *systemVersion = [[UIDevice currentDevice] systemVersion];
if ([systemVersion compare:@"10.0" options:NSNumericSearch] != NSOrderedAscending) {
    // iOS 10.0以上での処理
}

このコードでは、UIDeviceオブジェクトのsystemVersionプロパティから取得したシステムバージョンを文字列として取得し、compare:options:メソッドを使って数値的な比較を行っています。

この結果に基づき、iOS 10.0以上でのみ行いたい処理を分岐させることができます。

○バージョン判定方法4:特定のクラスやメソッドの存在チェック

Objective-Cでは、特定のクラスやメソッドがプログラムの実行時に存在するかどうかでバージョンを判定することも可能です。

これには、NSClassFromString()関数やrespondsToSelector:セレクタを使用します。

これらを用いることで、特定の機能が実行時の環境で利用可能かどうかを検出できます。

例えば、UIAlertControllerクラスはiOS 8.0で導入されましたが、それ以前のバージョンでは使用できません。

したがって、このクラスの存在をチェックすることで、実行しているiOSのバージョンが8.0以上かどうかを間接的に判定できます。

if (NSClassFromString(@"UIAlertController")) {
    // UIAlertControllerが存在する場合の処理(iOS 8.0以上)
} else {
    // UIAlertViewを使用するなどの古いバージョンでの処理
}

また、respondsToSelector:を用いた例としては、新しいメソッドが追加されたクラスに対して、そのメソッドが利用可能かどうかをチェックすることができます。

if ([someObject respondsToSelector:@selector(newMethod:)]) {
    [someObject newMethod];
} else {
    // 古いバージョンでの代替処理
}

この方法により、アプリケーションが柔軟に古いバージョンと新しいバージョンのiOSに対応できるようになります。

これらの判定は、アプリケーションが安定して動作し、より良いユーザー体験を提供するために重要です。

○バージョン判定方法5:プリプロセッサを使った条件コンパイル

Objective-Cにおいて、プリプロセッサを使った条件コンパイルは、コードが異なるバージョンのOSでコンパイルされるかどうかを判定する際に役立ちます。

この方法は、コンパイル時に定義されているマクロに基づき、コードの一部を有効または無効にするのに使用します。

たとえば、新しいAPIが追加されたiOSバージョンのみで特定のコードを利用する場合に重宝します。

#ifdef __IPHONE_11_0
// iOS 11.0で導入されたAPIを使用するコード
#else
// iOS 11.0未満のバージョンでの代替コード
#endif

この例では、iOS 11.0で導入されたAPIが利用可能かどうかをチェックしています。

__IPHONE_11_0マクロは、iOS 11.0またはそれ以降のバージョンでのみ定義されているため、この条件を満たす場合のみコンパイルされるコードを指定することができます。

○バージョン判定方法6:ランタイムの機能を利用する

ランタイムの機能を利用したバージョン判定は、実行時に特定のクラスやインスタンスが特定のメソッドをサポートしているかをチェックすることで行います。

Objective-Cのランタイム機能は強力で、isKindOfClass:isMemberOfClass:のようなメソッドを使用して、オブジェクトが特定のクラスのインスタンスであるかどうかを判定することが可能です。

if ([someObject isKindOfClass:[NewClass class]]) {
    // someObjectがNewClassのインスタンスである場合の処理
} else {
    // NewClassをサポートしていない場合の処理
}

このコードでは、someObjectNewClassのインスタンスであるかをランタイムでチェックし、それに基づいた処理を実行しています。

○バージョン判定方法7:APIの可用性チェック

iOS 12以降、Objective-CではAPI_AVAILABLEマクロを使用して、特定のAPIが利用可能なバージョンを表すことができます。

これにより、コンパイラは使用しているAPIが現在のターゲットに適しているかどうかをチェックし、不適切な場合には警告を発します。

このマクロを使用すると、開発者はAPIの可用性を明示的にコード内で宣言できます。

if (@available(iOS 10, *)) {
    // iOS 10.0以降で利用可能なコード
} else {
    // 古いバージョンのiOSでの処理
}

このコードスニペットは、@availableプラットフォームチェックを使用して、iOS 10.0以上で利用できる機能を安全に呼び出しています。

これは、新しいOS機能の採用を検討する際に、とても便利な方法です。

●Objective-Cのバージョン判定を使った応用例

Objective-Cのバージョン判定機能は、iOSアプリケーションの開発で非常に役立ちます。

アプリケーションのバージョン互換性を保ちながら、新しい機能を組み込む方法や、古いバージョンのiOSに対する適切な代替機能を提供する方法について、いくつかの応用例を見てみましょう。

○応用例1:異なるバージョンでの機能分岐

Objective-Cを使ってiOSの異なるバージョン間で機能を分岐させる際、@available構文を使ってコード内でチェックを行います。

下記のコードは、iOSのバージョンに応じて異なるUIAlertControllerのスタイルを適用する例を表しています。

if (@available(iOS 13.0, *)) {
    // iOS 13.0以降では、新しいスタイルのUIAlertControllerを使用
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Title" message:@"Message" preferredStyle:UIAlertControllerStyleAlert];
    // ここでalertにアクションを追加します
} else {
    // iOS 13.0未満では古いスタイルのアラートビューを使用
    UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Title" message:@"Message" delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
    // ここでalertを表示します
}

このコードを実行すると、iOS 13.0以降では新しいスタイルのアラートが表示され、それより前のバージョンでは古いスタイルのUIAlertViewが表示されます。

○応用例2:非推奨APIの代替案の提示

APIが非推奨になった場合、最新バージョンのAPIに移行するようにコードを更新することが重要です。

ここでは、古いメソッドを新しいメソッドに置き換える例を紹介します。

if (@available(iOS 10.0, *)) {
    // iOS 10.0以降で利用可能なUNUserNotificationCenterを使用
    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
    // 通知設定のコード
} else {
    // iOS 10.0未満でのUILocalNotificationを使用
    UILocalNotification* localNotification = [[UILocalNotification alloc] init];
    // 通知設定のコード
}

このコードは、iOS 10.0以降ではUNUserNotificationCenterを使用し、それ以前のバージョンではUILocalNotificationを使用しています。

○応用例3:新機能の採用判定

新しいOSバージョンで導入された新機能を使用するかどうかを判断する際も、バージョン判定は有効です。

ここでは、ホームスクリーンのクイックアクションを設定する例を紹介します。

if (@available(iOS 9.0, *)) {
    // iOS 9.0以降で3D Touchのクイックアクションを設定
    UIApplicationShortcutItem* shortcutItem = [[UIApplicationShortcutItem alloc] initWithType:@"com.example.MyApp.NewFeature" localizedTitle:@"New Feature" localizedSubtitle:nil icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeAdd] userInfo:nil];
    // ここでショートカットアイテムをアプリケーションに追加します
}

iOS 9.0以降で実行すると、アプリケーションは3D Touchのクイックアクションを利用できます。

これらの例は、Objective-Cのバージョン判定がいかにして開発プロセスを助け、エンドユーザーにとってより良い体験を提供するかを表しています。

●バージョン判定時の注意点と対処法

Objective-Cにおけるバージョン判定は、アプリケーションの多様なユーザーベースに対して、充実したサポートを提供する上で欠かせないものですが、実装する際にはいくつかの注意点があります。

その注意点と、遭遇する可能性のある問題に対する対処法を紹介します。

○注意すべきコンパイルエラー

バージョン判定コードを書く際には、誤って古いバージョンのAPIを使用してしまわないように注意が必要です。

コンパイルエラーは、多くの場合、使用しようとしているAPIが現在のビルド環境に存在しない場合に発生します。

これを防ぐためには、次のような対策を取ります。

  • Xcodeのビルドターゲット設定を確認し、最低限サポートするiOSバージョンを明確に設定する。
  • 古いバージョンのiOS向けには、#available@availableなどのAPI可用性チェックを適切に使用する。

例えば、新しい機能を含むコードブロックを書く際には、次のように@availableチェックを行います。

if (@available(iOS 12, *)) {
    // 新しいAPIや機能を安全に使用
} else {
    // iOS 12未満のデバイスでの代替コード
}

この方法を使用すると、iOS 12以前のバージョンでアプリケーションをビルドする際に、新しいAPIが原因でコンパイルエラーが発生するのを防ぐことができます。

○バージョン判定の最適化

バージョン判定コードは、アプリケーションの起動時や特定の機能が呼び出された時に複数回実行される可能性があります。

そのため、パフォーマンスに影響を与えないように、バージョン判定は最適化する必要があります。

例えば、次のように一度だけ実行するためのフラグを設定することが一つの方法です。

static BOOL isAPIAvailable = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    if (@available(iOS 12, *)) {
        isAPIAvailable = YES;
    }
});

if (isAPIAvailable) {
    // 新しいAPIを使用するコード
}

このコードでは、dispatch_onceを使用して、バージョンチェックを一度だけ行い、その結果を静的変数に保存しています。

これにより、同じチェックを何度も繰り返す必要がなくなります。

○間違った判定を避けるためのテクニック

間違ったバージョン判定は、アプリケーションのクラッシュや予期せぬ動作を引き起こす可能性があります。

正確なバージョン判定を行うためには、公式のドキュメントを参照し、各APIの導入されたバージョンを正確に理解することが重要です。

また、ベータ版のiOSに対するテストも重要です。

ベータ版を使ってテストを行うことで、将来のOSリリースに備えた準備ができます。

Objective-Cにおけるバージョン判定方法を適切に使用し、上記の注意点に留意することで、異なるバージョンのiOSを実行するデバイス上で、アプリケーションをより安全に、そして効率的に実行できるようになります。

●Objective-Cのバージョン判定のカスタマイズ方法

Objective-Cのバージョン判定は、標準のAPIやディレクティブを使用するだけでなく、プロジェクト固有の要件に合わせてカスタマイズすることができます。

カスタマイズすることで、より複雑な条件や、プロジェクト特有の機能を使用する際のバージョン管理が可能になります。

ここでは、ユーザー定義の判定条件の作成と、環境設定に基づくカスタム判定ロジックに焦点を当てて解説します。

○ユーザー定義の判定条件の作成

プロジェクト特有の条件をコード内で直接チェックする場合、自分で定義したフラグや関数を使ってバージョン判定を行うことができます。

たとえば、アプリケーションが特定の機能をサポートしているかどうかを、グローバル変数や関数を定義して管理する方法です。

// グローバル変数を定義
BOOL isFeatureXSupported = NO;

// アプリケーションの初期化時に、サポート状況をチェックする
void checkFeatureXSupport() {
    if (@available(iOS 12, *)) {
        isFeatureXSupported = YES;
    }
}

// このグローバル変数を使用して判定
if (isFeatureXSupported) {
    // 機能Xを使用するコード
}

この方法では、checkFeatureXSupport関数で一度だけOSのバージョンに基づくサポート状況をチェックし、その結果をグローバル変数に保存して使用します。

○環境設定に基づくカスタム判定ロジック

アプリケーションの設定やユーザーの環境に依存するバージョン判定を行う場合、環境変数や設定ファイルから情報を読み取り、動的にバージョン判定を行うことができます。

これにより、開発者はアプリケーションのビルド時やランタイム時に、異なる環境設定に応じた適切なコードを実行することができます。

// 環境設定を読み込む
NSDictionary *environmentSettings = ...; // 設定を読み込むコード
NSString *minRequiredVersion = environmentSettings[@"MinRequiredVersion"];

// 設定された最小要件と実行中のOSバージョンを比較
if ([[UIDevice currentDevice].systemVersion compare:minRequiredVersion options:NSNumericSearch] != NSOrderedAscending) {
    // 設定された最小バージョンを満たす場合の処理
}

この例では、事前に定義された環境設定から最小要件となるバージョン情報を取得し、実行中のデバイスのバージョンと比較しています。

これにより、開発中やリリース後のアプリケーションにおいて、柔軟なバージョン管理が実現できます。

まとめ

Objective-Cにおけるバージョン判定方法は、iOSやmacOSの異なるバージョン間でアプリケーションを適切に機能させるための重要な工程です。

この記事では、コンパイラディレクティブの使用からランタイムチェック、APIの可用性チェックに至るまで、7つの主要な方法を詳細に説明しました。

各方法は、開発環境とターゲットOSのバージョンに応じて適切に選択されるべきです。

このガイドが、Objective-Cでのバージョン判定の理解を深め、あなたのプロジェクトにとって実践的な助けとなることを願っています。