Swift 2: Проверка на доступность API

Swift 2: Проверка на доступность API

Обратите внимание, что эта статья описывает Swift 2, iOS 9 и Xcode 7. Если вы хотите продолжить, вам необходимо установить Xcode 7.

Как оно было раньше - ручная версия проверки

Без нововведений в Swift 2, вам приходилось проверять совместимость вручную. Например, если вы хотите использовать в своем приложении UIStackView, но также хотите поддержать пользователей iOS 8, вам нужно было сделать проверку версии операционной системы во время исполнения кода и отображать экземпляр UIStackView только при условии, что версия iOS его поддерживает. Например:

if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 9, minorVersion: 0, patchVersion: 0)) {
    print("Create the stack view!")
}

Этот метод перегружен проблемами, а ведь мы еще не сказали про необходимость помнить о том, когда был введен каждый компонент. Если ваше приложение пытается использовать iOS 9 на прошивке iOS 8, или iOS 8 на прошивке iOS 7, то оно упадет. Это означает, что разработчикам, заинтересованным в самых новейших интерфейсах API, приходилось тратить много времени, добавляя к своему коду проверки, с целью убедиться в том, что приложение не упадет.

Swift 2: автоматическая проверка доступности интерфейса API операционной системы

Возможно, это моя самая любимая часть во всем Swift 2. Частично потому, что облегчает жизнь разработчикам, частично потому, что описываемые в ней возможности, делают приложения более стабильными для конечных пользователей.

В Swift 2, Apple представила возможность проверки доступности интерфейса. Если вы ставите Deployment Target (самая старая из целевых версий операционных систем, которые должны поддерживать работу вашего приложения) ниже, чем версия базовая версия SDK (Base SDK), то Xcode автоматически просканирует все интерфейсы которые вы используете, для того, чтобы удостоверится что они доступны в самой старой версии Deployment Target. Эта информация была доступна в заголовках API Apple годами, но только сейчас была применена и к компиляторам. Это значит, что если ваше приложение компилируется, то это является гарантией того, что оно не вызывает какой-либо код, который не будет работать из-за отсутствия соответствующего API.

По умолчанию, вам не нужно ничего делать: Swift будет сравнивать фактическое использование с минимальной версией вашей deployment target, и если он находит любой недоступный интерфейс, то вы получите ошибку - и это именно то место, где вам придется хорошенько поработать.

Возвращаясь к нашему примеру, если вы использовали UIStackView и ваша цель развертывания установлена на 8.0, то вы получите ошибку компиляции, потому что stack views не доступен ранее 9.0. Решением будет сказать Xcode, что вы хотите, чтобы определенный код сработал только на iOS 9 или более поздней версии, как здесь:

if #available(iOS 9, *) {
    // use UIStackView
} else {
    // show sad face emoji
}

В этом коде #available проверит работаем ли мы на iOS 9 или более поздней версии, или на какой-то другой неизвестной платформе такой как, например, watchOS. Тогда на конце нужно поставить (*). Так это и работает: весь код, который вы поставите на место "// use UIStackView" будет иметь возможность использования только для iOS 9, будь то для классов, методов или перечислений.

Если код внутри метода должен работать только на определенных версиях IOS, вы так же можете использовать #available с guard, чтобы произвести такой код:

guard #available(iOS 9, *) else {
    return
}

Сила #available в том, что теперь компилятор может проверить и обеспечить использование интерфейса на старых операционных системах, что раньше можно было сделать только вручную. Это очень значительный прорыв и мы считаем, что это изменение приживется очень быстро.

Маркировка Swift 2 @available для методов и классов

Как вы могли заметить, у вас есть возможность использовать if #available для запуска кода, предназначенного для определенной версии операционной системы. Но что произойдет, если методы так же выходят за пределы версии системы или классы? Swift 2 также обрабатывает такие сценарии, используя атрибут @available.

@available работает аналогично атрибуту #available, в котором вы обозначаете исходную версию iOS, на которую ориентировано ваше приложение, а обо всем остальном позаботится Xcode. Например:

@available(iOS 9, *)
func useStackView() {
    // use UIStackView
}

Если вашим целевым развертыванием является iOS 8, то вы не можете вызвать метод useStackView() без какой-либо проверки на доступность. Вы можете объединить проверки, если это необходимо, например:

@available(iOS 7, *)
func iOS7Work() {
    // do stuff

    if #available(iOS 8, *) {
        iOS8Work()
    }
}

@available(iOS 8, *)
func iOS8Work() {
    // do stuff
    if #available(iOS 9, *) {
        iOS9Work()
    }
}

@available(iOS 9, *)
func iOS9Work() {
    // do stuff
}

Каждый раз появляется некоторая возможность улучшить ваш код при помощи новых алгоритмов, которые ограничены версией операционной системы.

Для максимальных ограничений вы можете маркировать целые классы, в качестве доступных только для определенных версий iOS или более поздних: просто перенесите код с атрибутом @available туда, куда вам нужно.

И последняя из особенностей проверки версии в Swift - вам не нужно больше беспокоиться о фреймворках "Required" и "Optional", так как компилятор сортирует их для вас. Да здравствует повышенная производительность разработчиков!

Оригинал: http://www.hackingwithswift.com/new-syntax-swift-2-availability-checking