Что такое Swift-эквивалент Objective-C "#ifdef __IPHONE_11_0"?

Я хочу использовать Xcode 9 для добавления кода iOS 11 в мой проект, сохраняя возможность компилировать проект с помощью Xcode 8, который поддерживает только iOS 10.

В Objective-C я могу это сделать, используя директиву препроцессора, чтобы проверить, существует ли __IPHONE_11_0. Это скроет код, если я компилирую базовый SDK раньше, чем iOS 11. Как это:

#ifdef __IPHONE_11_0
    if (@available(iOS 11.0, *)) {
        self.navigationController.navigationBar.prefersLargeTitles = YES;
    }
#endif

Есть ли способ сделать это в Swift?

if #available(iOS 11.0, *) не работает, потому что проверка времени выполнения.

Ответы

Ответ 1

IOS 11 SDK поставляется с Swift 3.2 (или Swift 4), поэтому вы можете использовать проверку версии Swift для выполнения той же самой задачи:

#if swift(>=3.2)
    if #available(iOS 11.0, *) {
        …
    }
#endif

Ответ 2

Это решение, предложенное Apple:

if #available(iOS 11.0, *) {
    // iOS 11 specific stuff here
} else {
    // non iOS 11 stuff here
}

Пожалуйста, обратитесь к этому ресурсу (смотрите видео на отметке 6:50 для более подробной информации).

Ответ 3

Если вы хотите поместить условие вне функции, вы можете сделать это, как показано ниже.

@available(iOS 11.0, *)
func functionName() {
 // function contents
}

Ответ 4

Я понимаю. У меня есть старый Mac, который мне нравится использовать, он слишком стар для Xcode 9, поэтому я хочу также иметь возможность иногда компилировать свои проекты под Xcode 8.

Но если все, что вам нужно, это поддерживать iOS 10 и iOS 11, самый простой способ - просто установить минимальный SDK цели Xcode на 10.0 и всегда компилировать с iOS 11 SDK. В этом случае Swift будет работать для вас и выдает синтаксические ошибки, если вы не используете правильно, если #available (iOS 11.0, *) {

Вы по-прежнему сможете тестировать как под iOS 10, так и под iOS 11, и вам не придется беспокоиться о Xcode 8.

С точки зрения Xcode 8, вы пытаетесь скомпилировать исходный код из будущего. Там нет хорошего решения для Xcode 8.

В перспективе вот решение:

В Xcode 9.3 (Swift 4.1) вы можете сказать:

#if canImport(MagiciOS12Kit)
  if #available(iOS 12.0, *) {
     MagiciOS12Class.standard.method()
  }
#endif

и ваш код будет по-прежнему компилироваться в Xcode 9.3, но пропускает тот будущий материал, который нуждается в гипотетическом Xcode 10.0 или более поздней версии.

#if canImport (moduleName) был добавлен только в Swift 4.1, который Xcode 8 не может обработать. Но даже это работает только для целых модулей, которые Apple добавит в будущем. Если Apple просто расширяет существующий класс новыми методами, как в вашем navigationController.navigationBar.prefersLargeTitles, вы все равно не сможете напрямую проверять prefersLargeTitles, но вы можете найти другую платформу, которую Apple представила одновременно с prefersLargeTitles, и проверить существование этого фреймворка с помощью #if canImport (…).

Ответ 5

Вы можете достичь, выполнив это для функции, как показано ниже

@available(iOS 11.0, *)
func myFunction() {
 // function defination 
}

Или, если вы хотите проверить внутри функции, напишите это

if #available(iOS 11.0, *) {
    // iOS 11 specific stuff here
} else if #available(iOS 10.0, *) {
   // iOS 10 specific stuff here
} else {
    // non iOS 11 & 10 stuff here
}