Доступность Swift во время компиляции: недоступный случай

В Swift есть хороший атрибут @ available для проверки доступности во время компиляции. Например. Идентификатор HKQuantityTypeIdentifierAppleExerciseTime доступен только с iOS 9.3, поэтому, если мы хотим его использовать, нам нужно проверить доступность следующим образом:

@available(iOS 9.3, *)
public static let supportedTypes = [
    HKQuantityTypeIdentifierActiveEnergyBurned,
    HKQuantityTypeIdentifierAppleExerciseTime
]

но можно ли добавить также случай, когда идентификатор недоступен? Чтобы определить ту же константу в iOS ‹ 9.3 как:

// iOS < 9.3 case:
public static let supportedTypes = [
    HKQuantityTypeIdentifierActiveEnergyBurned
]

person Vladimir    schedule 24.05.2016    source источник


Ответы (2)


Вы можете объявить переменную и инициализировать ее с помощью #available:

public static let supportedTypes: [String] = {
    guard #available (iOS 9.3, *) else { 
        return [ HKQuantityTypeIdentifierActiveEnergyBurned ] 
    }

   return [
       HKQuantityTypeIdentifierActiveEnergyBurned,
       HKQuantityTypeIdentifierAppleExerciseTime
   ]
}()

По сути, вы пытаетесь объявить одну из двух переменных с одинаковым именем и разными значениями по умолчанию, в зависимости от условия. Я думаю, что проще объявить одну переменную один раз, а затем присвоить ей значение по умолчанию в зависимости от того же условия. То же самое и с классами в основном.

person Alex Staravoitau    schedule 24.05.2016
comment
он компилируется с ошибкой: невозможно определить тип возвращаемого значения закрытия в текущем контексте - person Vladimir; 24.05.2016
comment
Да, извините, это было у меня в голове, и я забыл явно указать тип let (который, как жалуется компилятор, не может быть выведен из контекста). Я обновил свой ответ : [String] — не стесняйтесь попробовать еще раз. - person Alex Staravoitau; 24.05.2016

Мое текущее решение - использовать # available следующим образом:

static func setupTypes() -> [String] {
    if #available(iOS 9.3, *) {
        return [
            HKQuantityTypeIdentifierActiveEnergyBurned,
            HKQuantityTypeIdentifierAppleExerciseTime
        ]
    else{
        return [
            HKQuantityTypeIdentifierActiveEnergyBurned,
        ]
    }    
}

public static let supportedTypes:[String] = MyClass.setupTypes()

Но это дополнительное усложнение и к тому же не применимо ко всем классам, так что вопрос остается открытым.

person Vladimir    schedule 24.05.2016
comment
Пожалуйста, не думайте, что я защищаю собственное решение — скорее пытаюсь понять, чего вам нужно достичь. Я обновил свой ответ своими мыслями относительно осложнений, пожалуйста, дайте мне знать, если вы хотите предоставить больше информации о том, почему вам нужно следовать этому конкретному способу ведения дел, чтобы помочь мне и другим понять, что вы ищете. - person Alex Staravoitau; 25.05.2016
comment
@ Алекс, твой ответ в порядке, и я проголосовал за него. Но все еще жду других решений. Например. рассмотреть недоступный случай для всего класса. - person Vladimir; 26.05.2016
comment
Хорошо, конечно — хотя для классов, я думаю, применяется то же правило: вместо того, чтобы определять один из двух классов с одинаковым именем, вы можете определить один и настроить его поведение в зависимости от доступности API. - person Alex Staravoitau; 26.05.2016