Я пытаюсь создать универсальное приложение для iPhone, но оно использует класс, определенный только в более новой версии SDK. Фреймворк существует в более старых системах, но класс, определенный в фреймворке, не существует.
Я знаю, что хочу использовать какую-то слабую связь, но в любой документации, которую я могу найти, говорится о проверках существования функции во время выполнения - как мне проверить, существует ли класс?
ios
backwards-compatibility
weak-linking
психотик
источник
источник
Ответы:
TL; DR
Ток:
if #available(iOS 9, *)
if (@available(iOS 11.0, *))
if (NSClassFromString(@"UIAlertController"))
Наследие:
if objc_getClass("UIAlertController")
if (NSClassFromString(@"UIAlertController"))
if ([UIAlertController class])
Swift 2+
Хотя исторически рекомендуется проверять возможности (или наличие классов), а не конкретные версии ОС, в 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()
, вы получите следующую ошибку:Предыдущие версии 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 в этом документе, это :
источник
Class
экземпляр, возвращенныйNSClassFromString
(назначьте егоid
), и вызовите селекторы для этого экземпляра.canImport
. ПредложениеДля новых проектов, использующих базовый SDK iOS 4.2 или новее, есть этот новый рекомендуемый подход, который заключается в использовании метода класса 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-SW3
Этот механизм использует макрос NS_CLASS_AVAILABLE, который доступен для большинства фреймворков в iOS (обратите внимание, что могут быть некоторые фреймворки, которые еще не поддерживают NS_CLASS_AVAILABLE - проверьте примечания к выпуску iOS для этого). Также может потребоваться дополнительная настройка параметров, которую можно прочитать в приведенной выше ссылке на документацию Apple, однако преимущество этого метода заключается в том, что вы получаете проверку статического типа.
источник
UIAlertController
но все еще поддерживал iOS 7. Ответ code007 правильный, но требуется дополнительная конфигурация, чтобы слабо связать (установить сRequired
поOptional
) UIKit в вашем проекте (по крайней мере, для этой ситуации).