ios backwards-compatibility weak-linking

ios - Enlace Débil-verifique si existe una clase y use esa clase



backwards-compatibility weak-linking (2)

Intento crear una aplicación universal para iPhone, pero usa una clase definida solo en una versión más nueva del SDK. El marco existe en sistemas más antiguos, pero una clase definida en el marco no lo hace.

Sé que quiero usar algún tipo de enlace débil, pero cualquier documentación que pueda encontrar habla sobre verificaciones en tiempo de ejecución para la existencia de funciones. ¿Cómo puedo verificar que exista una clase?


TLDR

Corriente:

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

Legado:

  • Swift (versiones anteriores a 2.0) : if objc_getClass("UIAlertController")
  • Obj-C, iOS (versiones anteriores a la 4.2) : if (NSClassFromString(@"UIAlertController"))
  • Obj-C, iOS (versiones anteriores a 11.0) : if ([UIAlertController class])

Swift 2+

Aunque históricamente se ha recomendado comprobar las capacidades (o la existencia de clases) en lugar de versiones de sistema operativo específicas, esto no funciona bien en Swift 2.0 debido a la introducción de la verificación de disponibilidad .

Use de esta manera en su lugar:

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

Nota: Si en su lugar intentas usar objc_getClass() , obtendrás el siguiente error:

''️ ''UIAlertController'' solo está disponible en iOS 8.0 o posterior.

Versiones anteriores de Swift

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

Tenga en cuenta que objc_getClass() es más confiable que NSClassFromString() u objc_lookUpClass() .

Objective-C, iOS 4.2+

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

Vea la respuesta de code007 para más detalles .

OS X o versiones anteriores de iOS

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

Use NSClassFromString() . Si devuelve nil , la clase no existe, de lo contrario devolverá el objeto de clase que se puede usar.

Esta es la forma recomendada según Apple en este documento :

[...] Su código probaría la existencia de [a] clase usando NSClassFromString() que devolverá un objeto de clase válido si [la clase] existe o nula si no lo hace. Si la clase existe, tu código puede usarla [...]


Para los proyectos nuevos que usan un SDK base de iOS 4.2 o posterior, existe este nuevo enfoque recomendado que consiste en utilizar el método de clase NSObject para verificar la disponibilidad de clases débilmente vinculadas en tiempo de ejecución. es decir

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

fuente: https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/cross_development/Using/using.html#//apple_ref/doc/uid/20002000-SW3

Este mecanismo usa la macro NS_CLASS_AVAILABLE, que está disponible para la mayoría de los frameworks en iOS (tenga en cuenta que puede haber algún framework que aún no soporte NS_CLASS_AVAILABLE - revise la nota de la versión de iOS para esto). También es posible que se necesite una configuración de configuración adicional que se pueda leer en el enlace de documentación de Apple que se proporciona arriba, sin embargo, la ventaja de este método es que se obtiene una verificación de tipo estático.