Отрицание Objective-C ключевое слово @available
Я хотел бы запустить фрагмент кода, только если версия iOS текущего устройства ниже определенной версии, как указано здесь. Примеры кода, приведенные Apple, выглядят следующим образом:
if (@available(iOS 10.0, *)) {
// iOS 10.0 and above
} else {
// below 10.0
}
Однако существуют сценарии, в которых вы хотите запустить код только в том случае, если текущая версия iOS находится ниже определенной версии. Я предположил, что следующий код будет работать:
if ([email protected](iOS 10.0, *)) {
// below 10.0
}
Однако кажется, что это не работает, и я получаю следующее предупреждение от Xcode:
@available does not guard availability here; use if (@available) instead
Здесь - это фиксация LLVM, которая добавила диагностику, которую я вижу.
В эту проблему можно выделить два возможных варианта:
- Используйте вариант
if-else
без добавления кода в блок if
(не очень элегантный).
- Продолжайте использовать старые подходы, такие как
-[NSProcessInfo isOperatingSystemAtLeastVersion:]
.
Есть ли другой способ использования @available
, который мне не хватает?
Ответы
Ответ 1
Вы можете определить свои собственные пользовательские макросы, которые вы можете использовать в своем приложении. Пример: -
#define isIOS11() ([[UIDevice currentDevice].systemVersion doubleValue]>= 11.0 && [[UIDevice currentDevice].systemVersion doubleValue] < 12.0)
или
#define SinceIOS9_2 ([[UIDevice currentDevice].systemVersion doubleValue]>= 4.2 && [[UIDevice currentDevice].systemVersion doubleValue] < 9.2)
Используйте его, как показано ниже: -
if (isIOS11()) {
// Do something for iOS 11
} else {
// Do something iOS Versions below 11.0
}
Пожалуйста, дайте мне знать, если это сработает для вас.
Ответ 2
Идея @available
заключается в том, что вы хотите использовать API, который доступен только для определенных систем. Для других систем функциональность либо отсутствует в вашем приложении, либо вы предлагаете альтернативные функции. Правильный способ использовать его для случаев, когда вам не нужен какой-либо код за пределами определенной версии ОС, только ниже,
if (@available(iOS 10.0, *)) {
// Happens automatically on on iOS 10 and beyond
} else {
someOtherCode();
}
Причиной этого является то, что компилятор иногда должен выполнять некоторую дополнительную магию для кода, охраняемого @available
и поэтому ему необходимо четко распознать, когда это так. Поэтому на самом деле он явно ищет
if (@available(...)) {
допускается только изменение пробелов и разрывов строк. Да, вы можете опасаться, что один не (!
) Действительно ничего, кроме сложного, где бы вы тогда рисовали линию? Как насчет:
if ((todayIsTuesday() && @available(iOS 9.0, *))
|| (self.theWeatherIsNice && [email protected](iOS 11.0, *)) {
Таким образом, допускаются только простые утверждения, которые только заставляют компилятор разделить код на два раздела и где всегда будет работать только один раздел: один для перечисленных ОС и один для остальных. Разумеется, "остальное" можно затем разделить, else if
это разрешено. Только раздел else может быть автоматически сгенерирован, если отсутствует, поэтому, когда вы пишете это:
if (@available(...)) {
someCode();
} // There is no else
Компилятор также счастлив, так как это то же самое, что и
if (@available(...)) {
someCode()
} else {
// Nothing to do here
}