Можно ли отключить некоторые строки кода в Swift?

Я пытаюсь сделать свой код компилируемым как с Swift 1.2, так и с 2.0, не создавая новую ветку, используя макрос.

Макрос в Swift, который вы определили в пользовательских флагах Swift Compiler, не позволяет вам проверять условия так же свободно, как Obj-C.

Например, в объявлении функции, если она похожа на Obj-C. Я могу сделать что-то вроде этого.

class ThisIsAClass
{
    #if SWIFT_TWO_POINT_O
       func foo(bar bar: String)
    #else
       func foo(#bar: String)
    #endif
       {
          // Do some common code
          // ...
          // ...

          #if SWIFT_TWO_POINT_O
             print("Do 2.0 things")
          #else
             print("Do 1.2 things")
          #endif
       }
}

Проверка состояния макроса внутри функции в порядке. Но проверка условия для объявления функции не будет выполнена.

Есть ли способ добиться чего-то подобного.

Или разделить между ветвями Swift 1.2 и 2.0 - единственный способ.


person myLifeasdog    schedule 06.07.2015    source источник
comment
Надеюсь, это поможет вам: stackoverflow.com/a/24112024/3202193   -  person Ashish Kakkad    schedule 06.07.2015
comment
Проверка состояния макроса внутри функции в порядке. Но то, что я пытаюсь сделать, это проверка между функциями. Все равно спасибо.   -  person myLifeasdog    schedule 06.07.2015
comment
Вы не можете сделать это для языковых функций, только для функций фреймворка. Если вам нужно, чтобы исходный код был совместим как со Swift 1.2, так и со Swift 2.0, наличие двух отдельных веток — это действительно то, что вам нужно.   -  person Eric Aya    schedule 06.07.2015


Ответы (1)


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

Однако есть важная оговорка (выделено мной):

В отличие от операторов условной компиляции в препроцессоре C, операторы условной компиляции в Swift должны полностью окружать самодостаточные и синтаксически корректные блоки кода. Это связано с тем, что весь код Swift проверяется синтаксис, даже если он не скомпилирован.

Итак, вы не можете сделать:

#if SWIFT_ONE
func foo(/* swift 1 params */)
#else
func foo(/* swift 2 params */)
#endif
{
    // ... function body ...
}

... потому что func foo(params) не является синтаксически полным элементом. (Синтаксически полное объявление функции включает в себя тело функции.) То же самое, скажем, для попытки #if обойти объявление класса, но не его содержимое и т. д.

Так что вы можете сделать вместо этого?

  • в данном конкретном случае func foo(bar bar: String) вполне допустимый синтаксис Swift 1.x. # было просто сокращением для него... так что просто используйте аббревиатуру, и вам не придется беспокоиться о различиях языковых версий. (Тем не менее, не стесняйтесь писать о #foo и #bar в Твиттере.)

  • в более общем случае вы можете иметь несколько отдельных функций и отправлять их:

    func foo() {
        #if SWIFT_ONE
        fooForSwift1()
        #else
        fooForSwift2()
        #endif
    }
    
  • или для классов или других типов вы можете использовать псевдонимы типов:

    class Foo1 { /* ... */ }
    class Foo2 { /* ... */ }
    #if SWIFT_ONE
    typealias Foo = Foo1
    #else
    typealias Foo = Foo2
    #endif
    
person rickster    schedule 06.07.2015
comment
На самом деле, объявление функции не совсем проблема, но я выбрал это как пример отключения некоторых строк кода, потому что я думаю, что так это более понятно. Что меня действительно беспокоит, так это новая обработка ошибок в Swift 2.0. Но из документов Apple, на которые я следовал из вашего состояния ссылки, довольно ясно, что это потому, что весь код Swift проверяется синтаксис, даже если он не скомпилирован. Итак, я думаю, что у меня не может быть синтаксис Swift 2.0 (попробуй, поймай, выбрасывай ), если я хочу, чтобы он компилировался на компиляторе Swift 1.2. - person myLifeasdog; 07.07.2015
comment
почему Swift требует этого, это очень разочаровывает и приводит к большому количеству дублированного кода и странным обходным путям. - person odyth; 20.12.2016