Слабая связь-проверьте, существует ли класс и используйте этот класс


Я пытаюсь создать универсальное приложение для iPhone, но оно использует класс, определенный только в более новой версии SDK. Фреймворк существует в старых системах, но класс, определенный в фреймворке, не существует.

Я знаю, что хочу использовать какую - то слабую связь, но любая документация, которую я могу найти, говорит о проверке времени выполнения для существования функции-как я могу проверить, что класс существует?

2 81

2 ответа:

TLDR

ток:

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

наследие:

  • Swift (версии до 2.0):if objc_getClass("UIAlertController")
  • Obj-C, iOS (версии до 4.2): if (NSClassFromString(@"UIAlertController"))
  • Obj-C, iOS (версии до 11.0):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(), вы получите следующее сообщение об ошибке:

️ 'UIAlertController' доступен только на iOS 8.0 или новее.


предыдущие версии 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 в документ:

[...] Ваш код будет тестировать для существование класса [a] с использованием NSClassFromString() что вернется допустимый класс объект, если [] класс существует или нет, если это не так. Если класс существует, ваш код может его использовать [...]

для новых проектов, использующих базовый 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, который является доступно для большинство framework в iOS (Примечание могут быть некоторые рамки, которые еще не поддерживают NS_CLASS_AVAILABLE - проверьте примечание к выпуску iOS для этого). Также может потребоваться дополнительная настройка конфигурации, которую можно прочитать в приведенной выше ссылке документации Apple, однако преимущество этого метода заключается в том, что вы получаете статическую проверку типа.