Faible Linking - vérifier si une classe existe et l'utilisation de cette classe
-
27-09-2019 - |
Question
Je suis en train de créer une application iPhone universelle, mais il utilise une classe définie que dans une version plus récente du SDK. Le cadre existe sur les systèmes plus anciens, mais une classe définie dans le cadre ne fonctionne pas.
Je sais que je veux utiliser une sorte de liaison faible, mais toute la documentation, je peux trouver parle de contrôles d'exécution pour l'existence de la fonction - comment puis-je vérifier qu'une classe existe
La solution
TLDR
Courant:
- Swift :
if #available(iOS 9, *)
- Obj-C, iOS :
if (@available(iOS 11.0, *))
- Obj-C, OS X :
if (NSClassFromString(@"UIAlertController"))
Héritage:
- Swift (versions antérieures à 2.0) :
if objc_getClass("UIAlertController")
- Obj-C, iOS (versions antérieures à 4.2) :
if (NSClassFromString(@"UIAlertController"))
- Obj-C, iOS (versions antérieures à 11,0) :
if ([UIAlertController class])
Swift + 2
Bien qu'historiquement il a été recommandé de vérifier les capacités (ou l'existence de classe) plutôt que des versions spécifiques OS, cela ne fonctionne pas bien dans Swift 2.0 en raison de l'introduction de disponibilité vérifier.
Utilisez cette technique à la place:
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(...)
}
Remarque: Si vous essayez d'utiliser à la place objc_getClass()
, vous obtiendrez l'erreur suivante:
⛔️ 'UIAlertController' est uniquement disponible sur iOS 8.0 ou plus récent.
Les versions précédentes de Swift
if objc_getClass("UIAlertController") != nil {
let alert = UIAlertController(...)
} else {
let alert = UIAlertView(...)
}
Notez que objc_getClass()
est plus fiable que NSClassFromString()
ou objc_lookUpClass()
.
Objective-C, iOS 4.2 +
if ([SomeClass class]) {
// class exists
SomeClass *instance = [[SomeClass alloc] init];
} else {
// class doesn't exist
}
Voir réponse de code007 pour plus de détails .
OS X ou les versions précédentes d'iOS
Class klass = NSClassFromString(@"SomeClass");
if (klass) {
// class exists
id instance = [[klass alloc] init];
} else {
// class doesn't exist
}
Utiliser NSClassFromString()
. Si elle retourne nil
, la classe n'existe pas, sinon elle retournera l'objet de classe qui peut être utilisé.
Ceci est la méthode recommandée selon Apple dans ce document :
[...] Votre code testerait la existence de la classe [a] à l'aide
NSClassFromString()
qui retournera un objet de classe valide si [la] classe existe ou nul si elle doesnt. Si la classe n''existe, votre code peut l'utiliser [...]
Autres conseils
Pour les nouveaux projets qui utilise un SDK de base d'iOS 4.2 ou version ultérieure, il y a cette nouvelle approche recommandée qui consiste à utiliser la méthode de classe NSObject pour vérifier la disponibilité des classes faiblement liées à l'exécution. i.e..
if ([UIPrintInteractionController class]) {
// Create an instance of the class and use it.
} else {
// Alternate code path to follow when the
// class is not available.
}
Ce mécanisme utilise la macro NS_CLASS_AVAILABLE, qui est disponible pour plus cadre dans iOS (note il peut y avoir un certain cadre qui ne supportent pas encore le NS_CLASS_AVAILABLE - vérifiez la note de version iOS pour cela). configuration de réglage supplémentaire peut également être nécessaire que l'on peut lire dans le lien de la documentation d'Apple fournies ci-dessus, cependant, l'avantage de cette méthode est que vous obtenez la vérification de type statique.