Слабое связывание - проверьте, существует ли класс, и используйте этот класс - PullRequest
86 голосов
/ 17 июня 2010

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

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

Ответы [ 2 ]

161 голосов
/ 17 июня 2010

TLDR

Ток:

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

Legacy:

  • 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(), который вернет действительный объект класса, если класс []] существует, или nil, если его нет.Если класс существует, ваш код может использовать его [...]

69 голосов
/ 09 апреля 2012

Для новых проектов, в которых используется базовый 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, однако преимущество этого метода в том, что вы получаете статическую проверку типов.

...