Hey! Interested in an apt-get
repository for Swift 3.0? We’ve got packages for Xenial, Wily, and Trusty.
Swift 3.0 is introducing a number of changes, the least of which is moving to conformance of the ratified API naming conventions. If you read through the naming conventions you’ll see that the overarching theme is one of streamlining and simplification.
Let’s take a look at a few examples of this streamlining with this 2.2 script swiftcat.swift
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import Glibc guard Process.arguments.count == 2 else { print("Usage: swiftcat FILENAME") exit(-1) } let filename = Process.arguments[1] let BUFSIZE = 1024 var pp = popen("cat " + filename, "r") var buf = [CChar](count:BUFSIZE, repeatedValue:CChar(0)) while fgets(&buf, Int32(BUFSIZE), pp) != nil { print(String.fromCString(buf)!, terminator:"") } exit(0) |
Swift 3.0 changes the (count:repeatedValue)
function signature for array initialization to (repeating:count:)
. So rather than var buf = [CChar](count:BUFSIZE, repeatedValue:CChar(0))
we will use var buf = [CChar](repeating:0, count:BUFSIZE)
(note that we also simplified CChar(0)
to just 0
).
The fromCString
String
method has been removed in favor of an initializer in the form of init(cString:)
. As an initializer it also guarantees an object will be returned, so there’s no need for using the !
: print (String(cString:buf), terminator:"")
And finally, CommandLine
is used instead of Process
. Our new Swift 3.0 version of swiftcat.swift
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import Glibc guard CommandLine.arguments.count == 2 else { print("Usage: swiftcat FILENAME") exit(-1) } let filename = CommandLine.arguments[1] let BUFSIZE = 1024 var pp = popen("cat " + filename, "r") var buf = [CChar](repeating:0, count:BUFSIZE) while fgets(&buf, Int32(BUFSIZE), pp) != nil { print(String(cString:buf), terminator:"") } exit(0) |
Let’s take a look at another change in Swift 3.0 (which I appreciate), and that’s the named parameter is now required for the first argument to a function. For example, in Swift 2.2 the function func translate(text:String, from:String, to:String)
would be invoked with something like translate("Hello world", from:"en", to:"es")
. In Swift 3.0 the text
parameter label is required: translate(text:"Hello world", from:"en", to:"es")
.
A few more examples of changes made:
Regardless of what you think about the wisdom of this String
extension, this is functional Swift 2.2 code:
1 2 3 4 5 6 7 8 9 |
extension String { subscript (r: Range<Int>) -> String { get { let startIndex = self.startIndex.advancedBy(r.startIndex) let endIndex = self.startIndex.advancedBy(r.endIndex) return self[Range(start: startIndex, end: endIndex)] } } } |
The Swift 3.0 complains that value of type 'Index' (aka 'String.CharacterView.Index') has no member 'advancedBy'
. That’s because the function has changed from advancedBy(_:Index)
to advanced(by:Index)
(and somewhere buried in the API guidelines is a rationale as to the change).
Our next error is init(start:end:) is unavailable: use the '..<' operator
. I must admit that the ..<
operator looks weird (there, I said it), but okay, we’ll play along and update the code to return self[Range(startIndex..<endIndex)]
.
In-N-Out (Burger)
The placement of the inout
keyword has also changed. In Swift 2.2 our function for emulating certain ncurses
calls looked like this:
1 2 3 4 |
func getmaxyx(window:UnsafeMutablePointer<WINDOW>, inout y:Int32, inout x:Int32) { x = getmaxx(window) y = getmaxy(window) } |
That resulted in error: 'inout' before a parameter name is not allowed, place it before the parameter type instead
, so now we do this:
1 2 3 4 |
func getmaxyx(window:UnsafeMutablePointer<WINDOW>, y:inout Int32, x:inout Int32) { x = getmaxx(window) y = getmaxy(window) } |
Great Renaming
As a part of the Great Renaming the NS
prefix has been dropped from much of the Foundation classes. NSThread
is now Thread
, NSDate
is now Date
. You get the idea.
In addition to renaming classes, there has been a significant number of API changes centered around simplifying things. A great example of this simplification can be found in formatting dates and creating dates from strings. See our post on handling dates for more examples.
Notifications
Using NSNotificationCenter
has also changed between Swift 2.x and Swift 3.0. As a part of the Great Renaming the notification center is now simply named NotificationCenter
. For a complete writeup on notifications see our Notifications and userinfo with Swift 3.0 post.
But Wait!
Is that all there is to Swift 3.0 you ask? Of course not! The Swift Evolution repository has a complete list of all of the various changes. Have a look!
Get Started With Swift 3.0
There are a number of ways to start playing with Swift 3.0 today. Apple releases snapshot builds every so often on the official Download Swift page. Make sure and grab one of the Trunk Development (master) snapshots. The snapshots are in the form of .tar.gz
files that can be extracted on your filesystem.
If you’re running Ubuntu 14.04 or Ubuntu 15.10 and like the convenience of installing software with apt-get
, you can also try out our Swift 3.0 Ubuntu Packages.
Finally, get some practice. There’s some code in our moreswift Github repository that is all written in Swift 2.2. As an exercise download this code and try running with a Swift 3.0 compiler. There’s no telling what you’ll run into; if you find something that isn’t addressed here drop us a line so we can update the post.