Пометка фрагментов кода как доступных или недоступных для каждой платформы или версии требуется в постоянно меняющемся ландшафте разработки приложений. Когда появится новая версия Swift или версия платформы, мы хотели бы адаптироваться к ней как можно скорее. Не отказываясь от поддержки старых версий, мы можем использовать доступный атрибут в Swift.
Этот пост не поможет вам принять решение о том, какую минимальную версию iOS вы должны поддерживать, но он будет полезным справочником в тех случаях, когда вам нужно использовать более новые API.
Проверка версии ОС для выполнения кода
Базовый пример сводится к проверке конкретной версии ОС для выполнения фрагмента кода. Например, если вы хотите выполнить часть кода только для iOS 15 и выше, вы должны использовать доступный атрибут следующим образом:
if #available(iOS 15, *) {
print("This code only runs on iOS 15 and up")
} else {
print("This code only runs on iOS 14 and lower")
}
Вы также можете использовать доступный атрибут внутри оператора защиты:
guard #available(iOS 15, *) else {
print("Returning if iOS 14 or lower")
return
}
print("This code only runs on iOS 15 and up")
Это отлично подходит для случаев, когда вы хотите выполнить определенный код только для определенной версии iOS.
Разница между @available и #available
При навигации по Swift API вы часто сталкиваетесь с атрибутом @available. Мы только что рассмотрели #attribute, который похож, но немного отличается. Самый короткий ответ, чтобы описать его отличие:
- @available используется для обозначения доступности класса или метода.
- #available используется только для выполнения фрагмента кода для определенных платформ и/или версий.
Настройка доступности для класса или метода
Мы можем продемонстрировать это, пометив класс или метод как доступный с iOS 14:
@available(iOS 14, *)
final class NewAppIntroduction {
// ..
}
Как только вы попытаетесь создать экземпляр этого класса внутри проекта, который поддерживает версии ниже iOS 14, вы столкнетесь со следующей ошибкой:
Как видите, компилятор поможет нам исправить эту ошибку с помощью нескольких предложений. Два из них переместят проблему в другое место в вашем коде, пометив вызывающий класс как доступный, начиная с iOS 14. В этом случае нам поможет #available :
if #available(iOS 14, *) {
let appIntroduction = NewAppIntroduction()
} else {
// .. use the old app introduction
}
Мы могли бы сделать то же самое для методов, использующих атрибут @available:
@available(iOS 14, *)
func launchNewAppIntroduction() {
let appIntroduction = NewAppIntroduction()
}
Возможные значения атрибута available
В приведенных выше примерах мы использовали только проверки iOS 14. Однако с available атрибутом в Swift мы можем сделать гораздо больше.
Очевидно, мы могли бы заменить число 14 на любую доступную версию ОС. Платформа, в данном случае iOS, тоже может быть заменена. Список доступных атрибутов на сегодняшний день выглядит следующим образом:
- iOS
- iOSApplicationExtension
- macOS
- macOSApplicationExtension
- macCatalyst
- macCatalystApplicationExtension
- watchOS
- watchOSApplicationExtension
- tvОС
- tvOSApplicationExtension
- swift
Опции включают платформы, а также клавишу быстрого доступа для пометки фрагментов кода как доступных с определенной версии Swift.
Звездочка указывает на доступность объявления для всех названий платформ, перечисленных выше, если не указано иное. При необходимости вы также можете указать несколько платформ одновременно:
@available(iOS 15, macOS 12.0, *)
func launchNewAppIntroduction() {
let appIntroduction = NewAppIntroduction()
}
Пометка метода как deprecated или obsoleted
Другое значение атрибута используется для пометки методов как deprecated или obsoleted. Методы начинаются как deprecated и в конечном итоге будут помечены как obsoleted. Представьте себе, что у вас есть приложение, в котором введение приложения больше не будет отображаться на iOS 14 и более поздних версиях. Вы можете пометить конкретный метод, если он используется из SDK, как deprecated и obsoleted следующим образом:
@available(iOS, deprecated: 12, obsoleted: 13, message: "We no longer show an app introduction on iOS 14 and up")
func launchAppIntroduction() {
// ..
}
Когда разработчики нашего кода все еще пытаются использовать наши методы, они столкнутся со следующей ошибкой:
Нумерация версий при использовании этих значений часто сбивает с толку. В приведенном выше примере кода вы можете подумать, что этот метод deprecated в iOS 12 и obsoleted в iOS 13. Однако он читается по-другому:
- Этот метод deprecated в версиях выше, чем X
- Этот метод obsoleted в версиях выше X.
Сообщение используется для описания рассуждений и может быть полезно для объяснения изменений вашим разработчикам.
Пометка метода как переименованного
При разработке SDK для коллег, пользователей с открытым исходным кодом или других пользователей вы можете захотеть перевести разработчиков на более новые методы вашего кода. В этих случаях вы можете использовать переименованный атрибут:
@available(*, unavailable, renamed: "launchOnboarding")
func launchAppIntroduction() {
// Old implementation
}
func launchOnboarding() {
// New implementation
}
Обратите внимание, что сначала мы помечаем метод как недоступный. Переименованное значение указывает, какой метод следует использовать вместо этого.
Xcode хорошо поможет разработчикам, показав вариант исправления для нашего переименования:
Условие недоступности с использованием #unavailable
Часто задаваемый вопрос при работе с доступным атрибутом заключается в том, чтобы отменить оператор и написать код, например:
Запускайте это только в том случае, если версия iOS ниже X.
Swift 5.6 представил атрибут #unavailable в SE-290, позволяющий нам инвертировать доступную проверку следующим образом:
if #unavailable(iOS 15, *) {
// Run iOS 14 and lower code.
}
Вы в основном читаете это как:
Новый API недоступен, если ОС ниже iOS 15.
Использование недоступного атрибута чище, чем код, который вам приходилось писать до Swift 5.6:
if #available(iOS 15, *) { } else {
// Run iOS 14 and lower code.
}
Если вы читаете эту статью после обновления до Xcode 13.3, возможно, вы захотите проверить свои проекты на наличие фрагментов кода, подобных приведенным выше, и вместо этого перейти на использование проверки недоступности.
Использование нескольких недоступных платформ
Проверка недоступности также может использоваться с несколькими платформами, как и проверка доступности:
if #unavailable(iOS 15, watchOS 9) {
// Run on iOS 14, watchOS 8 and lower
}
Заключение
Мы рассмотрели все возможности использования атрибута available в Swift. Вы можете запускать код для определенной платформы и версий Swift, и теперь вы можете помечать методы как устаревшие, устаревшие или переименованные.