2

There are some related questions but I have insufficient site reputation to comment on the existing threads, forcing me to start a new one. Sorry about that.

It appears Swift doesn't have a true preprocessor. Workarounds are possible using #if / #else / #endif, but the problem here is that it doesn't hide the 'false' portion from the compiler, forcing both the 'true' and 'false' parts to be syntactically valid. This is tough given that Swift 3 is syntactically incompatible with Swift 2 -- has anyone found a workaround that will allow creating code that can be compiled for either environment? (If XCode 8 beta allowed Swift 2.2, or if XCode 7.3.1 allowed Swift 3, that would also give me a workaround here).

What I'm trying to do, to give just one trivial example, is something like

#if SWIFT3    
     let session = WCSession.default()
#else
     let session = WCSession.defaultSession()
#end

I can't find any way to do this, and it seems surprising that there isn't a way to do it given how completely incompatible Swift3 syntax is with Swift2.

Mike Yawn
  • 115
  • 1
  • 6
  • Swift 3 syntax is indeed very different than Swift 2. So much, so, that trying to paper over it with `#if` is not going to work, even if you had a pre-processor. The intended solution is to convert the code base to Swift 3 (or to fork it to Swift 3). Trying to maintain a non-trivial code base that compiles for both is a dead-end (just as it was for Swift 1 and Swift 2). – Rob Napier Jul 23 '16 at 17:06
  • @RobNapier I can't agree with that. It might not be morally advisable, but they did provide conditional compilation for exactly this purpose, and it does work. And I can imagine circumstances where conversion to Swift 3 needs to proceed piecemeal. – matt Jul 23 '16 at 17:09
  • @matt it'll be interesting to see that play out, but going from 1 to 2 I did not find that practical on any non-trivial code base. 2 to 3 is an even bigger change because it renames so many things. It's hard to imagine it working beyond very small pieces of code. But time will tell. – Rob Napier Jul 23 '16 at 17:15
  • @RobNapier That's right, but going from 1 to 2 `#if swift(...)` didn't exist; there wasn't conditional compilation. Now it does and there is. – matt Jul 23 '16 at 17:58
  • 1
    I agree that this is uglyfor a non-trivial code base, but mine probably qualifies as trivial. I have a reasonably large iOS app written in Objective-C, and to it I added a very small Watchkit Extension, for which I decided to learn Swift. I recently nstalled the XCode Beta and migrated the code to Swift 3, at which time I started having problems. In order to see whether the problems are mine or due to the beta, I'd really like to run it on XCode 7.3.1, but can't do that without reverting to Swift 2.2 -- hopefully just temporarily, and once XCode 8 is out of beta I can strip out the #ifs – Mike Yawn Jul 23 '16 at 21:23
  • Check this answer [http://stackoverflow.com/a/42785007/3177007](http://stackoverflow.com/a/42785007/3177007) It Works – Mohamed Jaleel Nazir Mar 14 '17 at 11:41

1 Answers1

8

I can't find any way to do this

Nevertheless, there is one, and there has been one since Swift 2.2; they planned ahead for exactly this contingency:

https://github.com/apple/swift-evolution/blob/master/proposals/0020-if-swift-version.md

So, like this (I don't know what a WCSession is, so I used a different example):

    #if swift(>=3.0)
        let screen = UIScreen.main()
    #else
        let screen = UIScreen.mainScreen()
    #endif

EDIT According to Apple, Xcode 8 permits passing of arbitrary conditional compilation flags to Swift:

Active Compilation Conditions is a new build setting for passing conditional compilation flags to the Swift compiler. Each element of the value of this setting passes to swiftc prefixed with -D, in the same way that elements of Preprocessor Macros pass to clang with the same prefix. (22457329)

matt
  • 515,959
  • 87
  • 875
  • 1,141