web-dev-qa-db-ja.com

弱いリンク-クラスが存在するかどうかを確認し、そのクラスを使用します

ユニバーサルiPhoneアプリを作成しようとしていますが、新しいバージョンのSDKでのみ定義されているクラスを使用しています。フレームワークは古いシステムに存在しますが、フレームワークで定義されたクラスは存在しません。

私は何らかの弱いリンクを使用したいと思っていますが、関数の存在のランタイムチェックに関する話を見つけることができるドキュメント-クラスが存在することを確認するにはどうすればよいですか?

86
psychotik

TLDR

現在:

  • Swiftif #available(iOS 9, *)
  • Obj-C、iOSif (@available(iOS 11.0, *))
  • Obj-C、OS Xif (NSClassFromString(@"UIAlertController"))

レガシー:

  • Swift(2.0より前のバージョン)if objc_getClass("UIAlertController")
  • Obj-C、iOS(4.2より前のバージョン)if (NSClassFromString(@"UIAlertController"))
  • Obj-C、iOS(11.0より前のバージョン)if ([UIAlertController class])

スイフト2+

歴史的には特定のOSバージョンではなく機能(またはクラスの存在)を確認することが推奨されていましたが、これはSwift 2.0の導入により でうまく機能しません可用性チェック

代わりにこの方法を使用します。

_if #available(iOS 9, *) {
    // You can use UIStackView here with no errors
    let stackView = UIStackView(...)
} else {
    // Attempting to use UIStackView here will cause a compiler error
    let tableView = UITableView(...)
}
_

注:代わりにobjc_getClass()を使用しようとすると、次のエラーが表示されます。

⛔️ 'UIAlertController'はiOS 8.0以降でのみ使用可能です。


Swiftの以前のバージョン

_if objc_getClass("UIAlertController") != nil {
    let alert = UIAlertController(...)
} else {
    let alert = UIAlertView(...)
}
_

objc_getClass()は、NSClassFromString()またはobjc_lookUpClass() よりも信頼性が高いことに注意してください。


Objective-C、iOS 4.2以降

_if ([SomeClass class]) {
    // class exists
    SomeClass *instance = [[SomeClass alloc] init];
} else {
    // class doesn't exist
}
_

詳細については、 code007の回答を参照してください


OS Xまたは以前のバージョンのiOS

_Class klass = NSClassFromString(@"SomeClass");
if (klass) {
    // class exists
    id instance = [[klass alloc] init];
} else {
    // class doesn't exist
}
_

NSClassFromString() を使用します。 nilを返す場合、クラスは存在しません。それ以外の場合は、使用可能なクラスオブジェクトを返します。

これは、Apple in this document

[...]コードはNSClassFromString()を使用して[a]クラスの存在をテストし、[the]クラスが存在する場合は有効なクラスオブジェクトを返し、存在しない場合はnilを返します。クラスが存在する場合、コードで使用できます[...]

161
Senseful

IOS 4.2以降のベースSDKを使用する新しいプロジェクトには、NSObjectクラスメソッドを使用して実行時に弱くリンクされたクラスの可用性をチェックする、この新しい推奨アプローチがあります。つまり.

if ([UIPrintInteractionController class]) {
    // Create an instance of the class and use it.
} else {
    // Alternate code path to follow when the
    // class is not available.
}

ソース: https://developer.Apple.com/library/content/documentation/DeveloperTools/Conceptual/cross_development/Using/using.html#//Apple_ref/doc/uid/20002000-SW

このメカニズムは、NS_CLASS_AVAILABLEマクロを使用します。このマクロは、iOSのmostフレームワークで使用できます(NS_CLASS_AVAILABLEをまだサポートしていないフレームワークがある可能性があります。これについては、iOSリリースノートを確認してください)。上記のAppleのドキュメントリンクで読むことができる追加の設定構成も必要になる場合がありますが、この方法の利点は静的な型チェックが得られることです。

69
code007