Estoy intentando 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.
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 la función: ¿cómo verifico que existe una clase?
ios
backwards-compatibility
weak-linking
psicotik
fuente
fuente
Respuestas:
TLDR
Actual:
if #available(iOS 9, *)
if (@available(iOS 11.0, *))
if (NSClassFromString(@"UIAlertController"))
Legado:
if objc_getClass("UIAlertController")
if (NSClassFromString(@"UIAlertController"))
if ([UIAlertController class])
Swift 2+
Aunque históricamente se ha recomendado verificar las capacidades (o la existencia de clases) en lugar de versiones específicas del sistema operativo, esto no funciona bien en Swift 2.0 debido a la introducción de la verificación de disponibilidad .
Use esta forma 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 cambio, intenta utilizar
objc_getClass()
, obtendrá el siguiente error: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 queNSClassFromString()
oobjc_lookUpClass()
.Objective-C, iOS 4.2+
if ([SomeClass class]) { // class exists SomeClass *instance = [[SomeClass alloc] init]; } else { // class doesn't exist }
Consulte la respuesta de code007 para obtener 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 }
Utilice
NSClassFromString()
. Si regresanil
, 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 :
fuente
Class
instancia devuelta porNSClassFromString
(asignarla aid
) e invocar selectores en esa instancia.canImport
. PropuestaPara proyectos nuevos que usan un SDK base de iOS 4.2 o posterior, existe este nuevo enfoque recomendado que consiste en usar 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 utiliza la macro NS_CLASS_AVAILABLE, que está disponible para la mayoría de los marcos en iOS (tenga en cuenta que puede haber algunos marcos que aún no sean compatibles con NS_CLASS_AVAILABLE; consulte la nota de la versión de iOS). Es posible que también se necesite una configuración de configuración adicional que se puede leer en el enlace de documentación de Apple proporcionado anteriormente, sin embargo, la ventaja de este método es que obtiene una verificación de tipo estática.
fuente
UIAlertController
mientras seguía siendo compatible con iOS 7. La respuesta de code007 es correcta, pero la configuración adicional necesaria es vincular débilmente (establecer deRequired
aOptional
) UIKit en su proyecto (para esta situación, al menos).