webentwicklung-frage-antwort-db.com.de

Schwache Verknüpfung - Überprüfen Sie, ob eine Klasse vorhanden ist, und verwenden Sie diese Klasse

Ich versuche, eine universelle iPhone-App zu erstellen, aber sie verwendet eine Klasse, die nur in einer neueren Version des SDK definiert ist. Das Framework ist auf älteren Systemen vorhanden, eine im Framework definierte Klasse jedoch nicht.

Ich weiß, dass ich eine Art schwache Verknüpfung verwenden möchte, aber in jeder Dokumentation, die ich finden kann, wird über Laufzeitprüfungen für die Existenz von Funktionen gesprochen. Wie überprüfe ich, ob eine Klasse vorhanden ist?

86
psychotik

TLDR

Aktuell:

  • Swift : if #available(iOS 9, *)
  • Obj-C, iOS : if (@available(iOS 11.0, *))
  • Obj-C, OS X : if (NSClassFromString(@"UIAlertController"))

Vermächtnis:

  • Swift (Versionen vor 2.0) : if objc_getClass("UIAlertController")
  • Obj-C, iOS (Versionen vor 4.2) : if (NSClassFromString(@"UIAlertController"))
  • Obj-C, iOS (Versionen vor 11.0) : if ([UIAlertController class])

Swift 2+

Obwohl es in der Vergangenheit empfohlen wurde, nicht nach bestimmten Betriebssystemversionen, sondern nach Fähigkeiten (oder Klassenexistenz) zu suchen, funktioniert dies in Swift= 2.0 wegen der Einführung der Verfügbarkeitsprüfung .

Verwenden Sie stattdessen diesen Weg:

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(...)
}

Hinweis: Wenn Sie stattdessen versuchen, objc_getClass() zu verwenden, wird die folgende Fehlermeldung angezeigt:

⛔️ 'UIAlertController' ist nur unter iOS 8.0 oder neuer verfügbar.


Frühere Versionen von Swift

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

Beachten Sie, dass objc_getClass()zuverlässiger ist als NSClassFromString() oder objc_lookUpClass() .


Objective-C, iOS 4.2+

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

Siehe die Antwort von code007 für mehr Details .


OS X oder frühere Versionen von iOS

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

Verwenden Sie NSClassFromString() . Wenn es nil zurückgibt, existiert die Klasse nicht, andernfalls gibt es das Klassenobjekt zurück, das verwendet werden kann.

Dies ist die empfohlene Vorgehensweise gemäß Apple in diesem Dokument :

[...] Ihr Code würde die Existenz einer Klasse mit NSClassFromString() prüfen, wodurch ein gültiges Klassenobjekt zurückgegeben wird, wenn [die] Klasse existiert, oder null, wenn dies nicht der Fall ist. Wenn die Klasse existiert, kann Ihr Code sie verwenden [...]

161
Senseful

Für neue Projekte, die ein Basis-SDK von iOS 4.2 oder höher verwenden, gibt es diesen neuen empfohlenen Ansatz, bei dem mithilfe der NSObject-Klassenmethode die Verfügbarkeit schwach verknüpfter Klassen zur Laufzeit überprüft wird. d.h.

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

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

Dieser Mechanismus verwendet das NS_CLASS_AVAILABLE-Makro, das für die meisten Frameworks in iOS verfügbar ist iOS Release Note für diese). Möglicherweise ist auch eine zusätzliche Einstellungskonfiguration erforderlich, die im oben angegebenen Dokumentationslink von Apple nachzulesen ist. Der Vorteil dieser Methode ist jedoch, dass Sie eine statische Typprüfung erhalten.

69
code007