Since Global Nerdy’s been so Apple-heavy as of late, I thought I’d offer this to those of you who are heavy into the Google love. I do try to be multi-platform, after all…
Click the graphic to see the Apple-fan-baiting at full size.
Update, July 24, 2014: I’ve updated this article to match the updates made to Swift with the release of Xcode beta 4. Gotta love languages in beta!
Welcome to another installment of Swift Kick, the series of articles on Global Nerdy covering programming in Apple’s new Swift programming language. Fell free to follow along and fire up your Xcode 6 beta, copy the examples, and experiment on your own! You can find earlier articles in this series by clicking on the Swift Kick logo to the right.
Spoiler alert! This article uses the events from the TV series Game of Thrones as a framework. You don’t need to have watched the series to understand this article, but it will reveal some plot points from the first three seasons.
Game of Thrones is popular among the sort of people who like programming, and given that the show often adds and (very brutally) deletes characters, I thought it would be a fun basis for an article on arrays in Swift.
Here are the Starks, the first family that we’re introduced to in the series:
In this article, we’re going to be working with an array representing the Stark Family. As you might expect, it’s called starkFamily
, and here’s its visual representation:
The Stark Family | |||||||
Parents | Children | ||||||
0 Ned (Dead) |
1 Catelyn (Dead) |
2 Robb (Dead) |
3 Jon (Alive) |
4 Sansa (Alive) |
5 Arya (Alive) |
6 Bran (Alive) |
7 Rickon (Alive) |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Here’s code to define the array and then display its contents:
var starkFamily = ["Ned", "Catelyn", "Robb", "Jon", "Sansa", "Arya", "Bran", "Rickon"] println(starkFamily)
Here’s the output of that code:
[Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon]
While most statements in Swift end at the end of a line, there are certain exceptions. One such exception is made for array literals, which you can write over several lines as shown below. I prefer defining longer arrays this way, as I find them easier to read:
var starkFamily = ["Ned", "Catelyn", "Robb", "Jon", "Sansa", "Arya", "Bran", "Rickon"]
If you’ve programmed in Python or Ruby, you’re familiar with this sort of thing, where the interpreter (or in Swift’s case, the compiler) “knows” that arrays and dictionaries can extend beyond a single line.
If you’re familiar with programming languages like C#, Java, JavaScript, Lua, Objective-C (more modern versions, anyway), PHP, Python and Ruby, you’ll find Swift’s basic array notation familiar — it’s good ol’ reliable arrayName[index]
, where arrayName
is the name of the array, and index
is an integer specifying which element of the array we want to retrieve. As with most programming languages, the first element of an array with n elements is at index 0, the second is at index 1, the third is at index 2, and so on up until the last element, which is at index n-1.
In the code snippet below, we want to access the 3rd and 6th elements of the starkFamily
array. Put another way, we want the starkFamily
elements at indices 2 and 5:
println("The Stark family member at index 2 is \(starkFamily[2]).") println("The Stark family member at index 5 is \(starkFamily[5]).")
Here’s the output of that code:
The Stark family member at index 2 is Robb. The Stark family member at index 5 is Arya.
The same array notation can be used to set array elements. In the code below, we want to change the contents of the element at index 0 from “Ned”, which is a nickname, to his proper name, “Eddard”:
starkFamily[0] = "Eddard" println(starkFamily)
Here’s the output:
[Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon]
Swift’s Array
type has two handy methods that answer these questions:
isEmpty
method returns true
if the array has no elements, false
otherwisecount
method returns the number of elements in the array. If the array is empty (that is, if isEmpty
returns true
), then count returns 0.For the code snippet below:
println("The statement that starkFamily is empty is \(starkFamily.isEmpty).") println("There are \(starkFamily.count) members in the Stark Family.")
the resulting output is:
The statement that starkFamily is empty is false. There are 8 members in the Stark Family.
Swift lets you get sub-arrays of an array by specifying a range of elements. This is one of those things that’s easier to show first, then tell afterwards, so I’ll let this picture do the talking first:
starkFamily[0..<3]
(with 2 dots and a <
, also known as the half-open range operator) specifies an array made of the elements of starkFamily starting at index 0, and up to but NOT including the element at index 3. If you’re mathematically inclined, you can think of 2 dots as defining a left-closed, right-open interval, which you write as [0, 3).starkFamily[0...3]
(with 3 dots, also known as the closed range operator) specifies an array made of the elements of starkFamily starting at index 0, and up to and including the element at index 3. If you’re mathematically inclined, you can think of 3 dots as defining a closed interval, which you’d write as [0, 3].Here some code showing array ranges in action. Let’s say we want to pull a couple of arrays out of starkFamily:
println("The parents in the Stark Family are \(starkFamily[0...1]).") println("The children in the Stark Family are \(starkFamily[2...7]).")
Here’s the output:
The parents in the Stark Family are [Eddard, Catelyn]. The children in the Stark Family are [Robb, Jon, Sansa, Arya, Bran, Rickon].
The half-open range operator is useful for when you want to retrieve a range of array elements starting at some given index, and going on for the rest of the array. You use it in conjunction with the count
property, like so:
println("The children in the Stark Family are \(starkFamily[2..<starkFamily.count]).")
Remember, in an array of n elements, the index of the last item is n – 1. Of course, you can always get an equivalent result with a 3-dot range…
println("The children in the Stark Family are \(starkFamily[2...starkFamily.count - 1]).")
…but in my opinion, that makes things more complicated than they need to be.
append
methodLet’s add some elements to the end of the array.
While Hodor doesn’t provide much in the way of conversation — the only thing he can say is his own name — he’s practically part of the Stark family. Let’s add him to the end of the starkFamily
array with the append
method. Here’s a representation of what that would look like:
Here’s the code:
println("Once again, the Stark Family:\n\(starkFamily)") println("Let's add Hodor!") starkFamily.append("Hodor") println(starkFamily)
and here’s the output:
Once again, the Stark Family: [Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon] Let's add Hodor! [Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon, Hodor]
+=
operatorLater in the series, Osha the wildling is taken prisoner and agrees to work for the Starks as a nanny, so she too is practically part of the family. Let’s add her to the starkFamily
array, but using the +=
operator instead. Here’s the visualization of that operation:
Here’s the code:
println("Once again, the Stark Family:\n\(starkFamily)") println("We'll add Osha:") starkFamily += "Osha" println(starkFamily)
And here’s the output:
Once again, the Stark Family: [Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon, Hodor] We'll add Osha: [Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon, Hodor, Osha]
+=
operatorIn the very first episode of Game of Thrones, the Starks come across a dead direwolf and several surviving pups. Each of the pups — eventually named Grey Wind, Lady, Numeria, Summer, Shaggydog, and Ghost — is taken by the Stark children as a pet, making them practically part of the family. Let’s put the direwolves’ names into an array, and then add that array to starkFamily
. Here’s the visualization:
The corresponding code:
var starkPets = ["Grey Wind", "Lady", "Nymeria", "Summer", "Shaggydog", "Ghost"] println("The Stark pets: \(starkPets)") starkFamily += starkPets println("The Stark family, with pets: \(starkFamily)")
And the output:
The Stark pets: [Grey Wind, Lady, Nymeria, Summer, Shaggydog, Ghost] The Stark family, with pets: [Eddard, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon, Hodor, Osha, Grey Wind, Lady, Nymeria, Summer, Shaggydog, Ghost]
What if we want to add elements to the array, but somewhere other than the end?
After his father’s failed rebellion against the Starks, Theon became a hostage and ward of the Stark family, who raised him as one of their own. Let’s add him to the family, between the two elder brothers, Robb and Jon, using the insert
method:
var starkFamily = ["Ned", "Catelyn", "Robb", "Jon", "Sansa", "Arya", "Bran", "Rickon"] println("Let's add Theon, between Robb (index 2) and Jon (index 3)") starkFamily.insert("Theon", atIndex: 3) println(starkFamily)
The output:
Let's add Theon, between Robb (index 2) and Jon (index 3) [Eddard, Catelyn, Robb, Theon, Jon, Sansa, Arya, Bran, Rickon, Hodor]
Want to add an element at the beginning of an array? Just use the insert
method to insert the new element at index 0.
The advice given to people new to Game of Thrones is to not get too attached to a character, because anyone — even a lead character — could die. This happened in season 1 when Ned was falsely accused and found guilty of treason:
…and then Catelyn and Robb (and a good chunk of the army of the North) were killed at the “Red Wedding”, which got this sort of reaction from viewers:
Let’s reflect these deaths by deleting them from the starkFamily
array. Here’s the visualization:
Here’s the code:
println(starkFamily) starkFamily = ["Ned", "Catelyn", "Robb", "Jon", "Sansa", "Arya", "Bran", "Rickon"] println("The Stark Family before: \(starkFamily)") starkFamily.removeAtIndex(2) starkFamily.removeAtIndex(1) starkFamily.removeAtIndex(0) println("The Stark Family after: \(starkFamily)")
And here’s the output:
The Stark Family before: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon] The Stark Family after: [Jon, Sansa, Arya, Bran, Rickon]
There’s a reason I removed element 2, then element 1, then element 0 rather than starting with element 0 and worked my way up. I’m going to leave it to you to figure why I did it that way.
Suppose we want to get rid of the last element in starkFamily
. One way to do it is to use the count
property of the array to get the array’s size, then subtract 1 from it to get the last index of the array. Then, you’d use the removeAtIndex
method to remove that element. It’s done in a single line of code:
starkFamily.removeAtIndex(starkFamily.count - 1)
While it’s simple, there’s an even simpler way that doesn’t require you to calculate the last index of the array. It’s the removeLast
method, and it removes the last element of the array. Here’s the visualization:
Here’s the code:
starkFamily = ["Ned", "Catelyn", "Robb", "Jon", "Sansa", "Arya", "Bran", "Rickon"] println("The Stark Family before: \(starkFamily)") starkFamily.removeLast() println("The Stark Family after: \(starkFamily)")
The output:
The Stark Family before: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon] The Stark Family after: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran]
Let’s cross over to another popular show that airs on Sunday nights: Mad Men. As ill-advised as many of the choices made by the heads of the Stark family were, chances are those choices might by much worse if they were made by Don and Betty Draper. Still, people who make good choices don’t make good drama, so let’s go ahead and replace Ned and Catelyn with Don and Sally.
We could perform the replacement element by element:
starkFamily[0] = "Don" starkFamily[1] = "Betty"
But we can reduce this operation to a single line by specifying a range in our array, and assigning a replacement array:
For this code:
starkFamily = ["Ned", "Catelyn", "Robb", "Jon", "Sansa", "Arya", "Bran", "Rickon"] println("The Starks: \(starkFamily)") starkFamily[0...1] = ["Don", "Betty"] println("The Draper-Starks: \(starkFamily)")
We get this output:
The Starks: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon] The Draper-Starks: [Don, Betty, Robb, Jon, Sansa, Arya, Bran, Rickon]
In season 4 of Mad Men, Betty had divorced Don and his second bachelorhood is in full swing. Let’s represent this with an array containing only Don, and let’s use this array to replace the range in starkFamily
containing Ned and Catelyn. Here’s a visualization of the result:
Here’s the code:
starkFamily = ["Ned", "Catelyn", "Robb", "Jon", "Sansa", "Arya", "Bran", "Rickon"] println("The Starks: \(starkFamily)") starkFamily[0...1] = ["Don"] println("The Draper-Starks: \(starkFamily)")
And here’s the output:
The Starks: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon] The Draper-Starks: [Don, Robb, Jon, Sansa, Arya, Bran, Rickon]
Later in the Mad Men series, Don marries his second wife, Megan. Let’s treat Don, Betty, and Megan as an array of parents and use them to replace Ned and Catelyn in starkFamily
. Here’s the visualization of that arrangement:
Here’s the code:
starkFamily = ["Ned", "Catelyn", "Robb", "Jon", "Sansa", "Arya", "Bran", "Rickon"] println("The Starks: \(starkFamily)") starkFamily[0...1] = ["Don", "Betty", "Megan"] println("The Draper-Starks: \(starkFamily)")
And here’s the output:
The Starks: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon] The Draper-Starks: [Don, Betty, Megan, Robb, Jon, Sansa, Arya, Bran, Rickon]
Earlier in this article, we represented the deaths of Ned, Catelyn, and Robb by deleting them from the starkFamily
array one at a time. Since Ned’s, Catelyn’s, and Rob’s elements are all in a row in the range [0...2]
, we can delete them in a single action by replacing that range with an empty array. Here’s the visualization:
Here’s the code:
starkFamily = ["Ned", "Catelyn", "Robb", "Jon", "Sansa", "Arya", "Bran", "Rickon"] println("The Stark Family before: \(starkFamily)") starkFamily[0...2] = [] println("The Stark Family after: \(starkFamily)")
And here’s the output:
The Stark Family before: [Ned, Catelyn, Robb, Jon, Sansa, Arya, Bran, Rickon] The Stark Family after: [Jon, Sansa, Arya, Bran, Rickon]
There’s more in the Collections Types chapter of Apple’s The Swift Programming Language, and I’ll cover more in part 2 as well.
Click the image to see Swift language projects on GitHub.
Apple’s documentation, The Swift Programming Language, is a pretty decent read, but its examples are geared around showing individual language features and not around building full-blown apps. With Swift having been released to registered Apple developers a mere three days ago and the NDA preventing the posting of screenshots of iOS 8 and Xcode 6 until their general release, we’re going to be short on books and detailed tutorials for the next few months. So how’s a developer to learn about Swift and still play within the rules of their developer agreement with Apple?
The answer: Github. More accurately, Swift projects on Github. And there are more of them than you might think.
As I write this (10:00 a.m. EDT, June 5, 2014), even though it’s been less than 72 hours since the beta of Xcode 6 (and therefore Swift) was made available for download, there are already about 350 repos on Github marked as being done in Swift. There may be more by the time you read this.
Update: As of 1:45 p.m. EDT, June 5, 2014, there are 370 Swift repos in Github.
Some of these repos are simple experiments with Swift and its syntax, some are tests of interacting with various API using Swift, some are the sort of mini-apps you build when learning a new language, and then there’s this:
That’s right: it’s an implementation of Flappy Bird in Swift. If you’ve always wanted to learn SpriteKit and now want to learn Swift, go to the FlappySwift repo on GitHub and kill two — ahem — birds with one stone.
Keep an eye on Swift projects in Github; I’m sure that their numbers will keep growing. And don’t forget to make your own contribution!
Let’s dive into Swift! For the next several articles, I’m going to share my observations as I noodle around with Swift on the Xcode 6 beta and try to get a feel for the language.
Keep in mind that Swift is in beta, and given the loose way “beta” is defined in these agile, pivot-happy days, it could be subject to all sorts of changes that may invalidate some of what I cover here.
We’ll start off with a couple of variable declarations, and then we’ll print them out on the console. Here’s the code:
var name = "Dëathtöngüë" var radius = 4.0 println("Hey, \(name), we're working with a radius of \(radius).\n")
And here’s its output:
Hey, Dëathtöngüë, we're working with a radius of 4.0.
Note that unlike Objective-C (or C, or most other languages that borrow its syntax), the lines of code above don’t end in semicolons. Swift is like JavaScript in that a line break is enough to mark the end of a statement, and ending them with semicolons is optional (much to the chagrin of the pro-mandatory-semicolon people in the Great JavaScript Semicolon Debate). You do need to use a semicolon to separate statements if you want to put them on the same line. For example, the following code compiles:
var name = "Dëathtöngüë"; var radius = 4.0; println("Hey, \(name), we're working with a radius of \(radius).\n");
My recommendation: follow the style in Apple’s example code, be like our friends in the Lua, Python, and Ruby worlds, and don’t use semicolons to separate statements.
Note that we didn’t have to specify the types of the name
and radius
variables. All we did was declare them with the var
keyword, and then we assigned values to them:
var name = "Dëathtöngüë" var radius = 4.0
This code is legal JavaScript, but it’s rather different underneath. JavaScript associates types with values, while Swift associates types with variables. The compiler infers the variables’ types from the values assigned to them:
name
was assigned a string literal, which means that it should be of type String
, andradius
was assigned a numeric literal with a decimal point, so the compiler assigned it the type Double
.This feature goes by names like type inference and implicit typing. We’ve had this in C# since late 2007, and it’s nice to see it in Swift.
The basic types that I’ve encountered in the documentation so far are:
Int
Float
Double
Bool
(whose values are true and false as opposed to Objective-C’s YES and NO)String
The println()
function sends output to the console. It’s capable of outputting all of Swift’s basic types without your having to convert them to String
first. All of the following lines work in Swift:
println(5) println(5.5) println(5 * 5) println(true) println("Five by five, chief.")
\()
is used for string interpolation, in a manner similar to Ruby’s and CoffeeScript’s #{}
.
Let’s take our initial code and add a function that calculates the area of a circle, given its radius:
var name = "Dëathtöngüë" var radius = 4.0 println("Hey, \(name), we're working with a radius of \(radius).\n") func circleArea(circleRadius: Double) -> Double { let π = 3.14 return π * circleRadius * circleRadius } println("The circle's area is \(circleArea(radius)).")
Here’s its output:
Hey, Dëathtöngüë, we're working with a radius of 4.0. The circle's area is 50.24.
Function headers in Swift have the following format… …and they’re bounded by braces —
{
and }
— just like in Objective-C and every other C-like language. The return
keyword works as you’d expect it to: it specifies the function’s return value and returns program control to whatever called the function in the first place.
There’s a lot more to function definitions, and I’ll cover than in a later article.
Take a closer look at the definition inside the circleArea
function:
let π = 3.14
Just as var
is used to declare variables, let
is used to declare constants. As with variables, if there’s enough information in the value you’re assigning to the constant, the compiler will infer its type.
As you might expect, any attempt to redefine a constant results in an error. After all, a redefinable constant is a variable.
In our constant declaration, we used the greek letter π
(which you get by typing option-p) instead of pi.
Swift’s source files are Unicode, which means that you’re not limited to the Roman character set for naming things. This feature is meant to let people whose native languages with non-Roman alphabets give more meaningful names to their variables, constants, functions, classes, and so on.
As I wrote in an earlier post, it also lets you use emoji, which may be useful for amusing demos or in the event someone declares an Obfuscated Swift programming contest.
There are times when the compiler just doesn’t have enough information to infer the type of a variable. For instance, if you make the following declaration…
var someValue = 3.0
…the compiler will assume that someValue
‘s type is Double
. What if you need someValue
to be a Float
instead? You’ll need to specify its type, as shown below:
var someValue:Float = 3.0
If you need to declare a variable but don’t want to assign a value to it immediately, you’ll also have to specify its type, as the compiler won’t have enough information to infer it:
var finalScore:Int var playerToBeNamedLater:String var iDontFeelLikeTypingADecimalPoint:Double = 3
Try the following code, but take note: it won’t work!
// This code won't work! func circleArea(circleRadius: Double) -> Double { let π = 3.14 return π * circleRadius * circleRadius } var floatRadius:Float = 3.0 // Here's where the error occurs: println("The other circle's area is \(circleArea(floatRadius)).")
The problem is that you’re passing a Float
to a function that expects a Double
parameter. You need to convert floatRadius
into a Double
first. Luckily that’s pretty simple — all the basic types have conversion functions:
Int()
takes a numeric or Bool
argument and returns its Int
equivalent, with the fraction removed (not rounded). The Bool
value true
is converted to 1
, false
is converted to 0
.Float()
takes a numeric argument and returns its Float
equivalent. You lose decimal precision if you use Float()
on a Double
, and gain some if you use it on an Int
. The Bool
value true
is converted to 1.0
, false
is converted to 0.0
.Double()
takes a numeric argument and returns its Double
equivalent. You gain decimal precision if you use Double()
on an Int
or Float
. The Bool
value true
is converted to 1.0
, false
is converted to 0.0
.Bool()
takes a numeric or String
argument and returns its Bool
equivalent. As far as I can tell, only 0
equates to false
; everything else — even the empty string ""
— equates to true
. I tried Bool(nil)
and got an error.String()
takes a numeric argument and returns its String
equivalent.This code works, because we use Float()
to convert floatRadius
into a Double
before passing it to circleArea()
:
func circleArea(circleRadius: Double) -> Double { let π = 3.14 return π * circleRadius * circleRadius } var floatRadius:Float = 3.0 // We have to convert floatRadius to a Double before // passing it to circleArea(). println("The other circle's area is \(circleArea(Double(floatRadius))).")
Craig Federighi talks about Swift’s swiftness.
The payoff for all this fussiness about type is speed. As Matt Galloway writes in his Swift Language Highlights article on RayWenderlich.com:
In Swift, the compiler knows much more [than Objective-C] about the types in play in any method call. It knows exactly where [any given function or method] is defined. Because of this, it can optimise certain call sites by jumping directly to the implementation rather than having to go through dynamic dispatch. In other cases, it can use vtable style dispatch, which is far less overhead than dynamic dispatch in Objective-C. This is the kind of dispatch that C++ uses for virtual functions.
If you’re a regular reader of this blog, chances are that you’re itching to take Apple’s new programming language, Swift, out for a spin. Global Nerdy’s largely about mobile technology these days, and since I’m looking to make it more about mobile development as well, I thought “Hey, here’s a great opportunity to write about programming and cover something new and exciting. I’ve already got my hands on the Xcode 6 beta and iOS 8, as well as Apple’s Swift programming book, and will be noodling with the language for the next little while. I’ll post my observations here, under the category “Swift Kick”.
(If you think that name is silly, my friend David Janes came up with a worse one: “Tailored Swift”. I may still use that name for a presentation.)
I was going to make a tailored Swift joke but apparently the entire Internet already beat me to it.
— Jan/Ian Eilander (@jeilander) June 2, 2014
The Swift site, located at developer.apple.com/swift/, is open to the general public and the first place you should head. Its landing page gives you a quick overview of the language and provides a number of useful links, including the online edition of the ebook The Swift Programming Language.
There’s a reason RayWenderlich.com is one of the go-to sites for iOS developers: they’ve got great articles, and they’re quick to put out tutorials on how to use the latest iDevelopment tools. They’ve done it again by putting out a cheat sheet and reference card for Swift.
And finally, there’s a Swift tag — swift-language — in Stack Overflow, and as of this writing (2:00 pm on Tuesday, June 3, 2014), there are 155 questions with this tag.
If you have a Mac (necessary if you want to developer for iOS) or an iPhone/iPad/iPod Touch, you can get your hands on the iBook The Swift Programming Language, which is available for free.
If you’re a registered iOS or OS X developer, you’ll be able to download the betas for Xcode 6 and iOS 8. Remember that this is beta code: don’t build anything that you’re putting on the market with the Xcode beta, and don’t install the iOS beta on a device that’s critical to your work!
Ole Bergmann points out that Apple has eased up on their NDA (non-disclosure agreement) for the iOS 8 / OS X Yosemite releases. He points to this sentence in the agreement from section 10.1, titled Information Deemed Apple Confidential:
Further, Apple agrees that You will not be bound by the foregoing confidentiality terms with regard to technical information about pre-release Apple Software and services disclosed by Apple at WWDC (Apple’s Worldwide Developers Conference), except that You may not post screen shots, write public reviews or redistribute any pre-release Apple Software or services.
It appears to mean that we can talk about material that’s covered in the Swift book, at the very least. Can anyone enlighten us and tell us what else we can talk about?
By allowing Unicode characters in constant and variable names, Apple’s new Swift programming language will allow programmers whose native languages don’t use the Roman alphabet to write code that makes more sense to them. Since emoji are part of the Unicode set, expect to see amusing code demos and search-and-replace pranks that look like this:
(And yes, this code compiles and runs on Swift using the XCode 6 beta.)
…the Samsung copier.