3

I trying to make my code compilable with both Swift 1.2 and 2.0, without creating a new branch, by using macro.

Macro in Swift that you defined in custom Swift Compiler flags doesn't allow you to check the conditions as freely as Obj-C.

For example, in function declaration, if it like Obj-C. I can do something like this.

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
       }
}

Macro condition checking within the function is fine. But the condition checking for declaring function will failed.

Is there a way I can achieve something like this.

Or separate between Swift 1.2 and 2.0 branches is the only way.

myLifeasdog
  • 1,959
  • 2
  • 13
  • 11
  • Hope this helps you : http://stackoverflow.com/a/24112024/3202193 – Ashish Kakkad Jul 06 '15 at 09:07
  • Macro condition checking within the function is fine. But what I trying to do is checking across and between the function. Thank you anyway. – myLifeasdog Jul 06 '15 at 09:25
  • 3
    You can't do that for language features, only for frameworks features. If you need your source to be compatible with both Swift 1.2 and 2.0, having two separate branches is indeed the way to go. – Eric Aya Jul 06 '15 at 09:33

1 Answers1

3

Yes, you can define compiler flags and check them to conditionally compile parts of your source, as noted in the docs.

However, there's an important caveat (emphasis added):

In contrast with condition compilation statements in the C preprocessor, conditional compilation statements in Swift must completely surround blocks of code that are self-contained and syntactically valid. This is because all Swift code is syntax checked, even when it is not compiled.

So you can't do:

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

...because func foo(params) is not a syntactically complete element. (A syntactically complete function declaration includes the function body.) Ditto for, say, trying to #if around a class declaration but not its contents, etc.

So what can you do instead?

  • in this particular case, func foo(bar bar: String) is perfectly valid Swift 1.x syntax. The # was merely a shorthand for it... so just use the longhand and you won't have to worry about language-version differences. (Feel free to post about #foo and #bar on Twitter, though.)

  • more generally, you can have multiple separate functions and dispatch to them:

    func foo() {
        #if SWIFT_ONE
        fooForSwift1()
        #else
        fooForSwift2()
        #endif
    }
    
  • or for classes or other types, you can use type aliases:

    class Foo1 { /* ... */ }
    class Foo2 { /* ... */ }
    #if SWIFT_ONE
    typealias Foo = Foo1
    #else
    typealias Foo = Foo2
    #endif
    
rickster
  • 124,678
  • 26
  • 272
  • 326
  • Actually, The function declaration is not quite a problem but I choose that to be an example of disable some lines of code because I think it more clear that way. What really bother me is the new error-handling in Swift 2.0. But from the Apple docs I followed from your link state pretty clear that "This is because all Swift code is syntax checked, even when it is not compiled.". So, I think I can't have Swift 2.0 syntax (try, catch, throws) if I want it to compilable on Swift 1.2 compiler. – myLifeasdog Jul 07 '15 at 05:38
  • why does swift require this, it is super frustrating and leads to lots of duplicate code and weird work arounds. – odyth Dec 20 '16 at 01:13