The following is an excerpt from a book I’m writing on iOS 9 development.
An array is a collection of elements, all of the same type, each of which has an index. Elements in an array are therefore ordered by their indices. If we’re collecting frogs (oh, no, not more frogs… please…), we might organize them in an array of Strings called myFrogs:
Once we have our array, we can find a particular frog using its index: myFrogs is Betty, for example.
Notice that the index numbers start with zero, not one. Some modern programming languages use 1-based arrays, but Swift is an example of a modern language that does not. If we think about how the array might be stored in memory, it’s easy to see that the index is really a memory offset from the beginning of the array:
The distance from the beginning of the array to the first character in “Benny” is zero, therefore the index of Benny is 0. Zero indexing is an artifact of how a programming language is implemented that surfaces to how the language is used. Don’t let it bother you, with a little practice you’ll start counting with zero too!
If we know all the elements of an array beforehand, we can declare it like this:
let myFrogs = [“Benny”, “Billy”, “Betty”, “Bo”]
This is a constant declaration, and would be used if we were never going to add or remove any frogs from our array. We could also declare myFrogs as a variable:
var myFrogs = [“Benny”, “Billy”, “Betty”, “Bo”]
We can now add or remove frogs at will. But what is the type of this array? In other words, what sort of annotation would we use to declare an empty array of String? Since we would probably never want an array of frogs that remained empty forever (well, you might; I wouldn’t, obviously), let’s declare it as a var:
var myFrogs : [String] = [ ]
Let’s pick that one apart. The type of myFrogs is [String], meaning “an array of type String.” Enclosing the type name in square brackets creates an array of that type. This array is initialized to the empty array: [ ]. We can now add elements to the array by calling the .append() method:
myFrogs.append("Benny") // [“Benny]”
myFrogs.append("Billy") // [“Benny”, “Billy”]
myFrogs.append("Betty") // [“Benny”, “Billy”, “Betty”]
myFrogs.append("Bo") // [“Benny”, “Billy”, “Betty”, “Bo”]
or remove them by calling .removeAtIndex()
myFrogs.removeAtIndex(2) // [“Benny”, “Billy”, “Bo”]
Removing a frog from the array doesn’t leave a “frog shaped hole” in the array. The array collapses. Taking the value at index 2 now returns “Bo.”
myFrogs // “Bo”
The .append method always adds items to the end of the array. Another way to do this is to use the “addition assignment” operator ( += ).
myFrogs += [“Bert”] // [“Benny”, “Billy”, “Bo”, “Bert”]
Because of Swift’s strong type checking, we can’t add a String to a [String], but we can add an array of String. In this example, we’re adding an array containing one string (“Bert”) to an array that already contains three (“Benny”, “Billy”, and “Bo”). There’s therefore nothing holding us back from adding any two arrays, as long as they have the same types:
let yourFrogs : [String] = ["Chester", "Charlie", "Celine", "Claude"]
let ourFrogs = myFrogs + yourFrogs
The new array ourFrogs is [“Benny”, “Billy”, “Bo”, “Bert”, "Chester", "Charlie", "Celine", "Claude"].
As long as an array is declared as a var, any element can be changed by assigning a new value to that element of the array:
myFrogs = “Boris”
But a new element can’t be added to the array by using an index that doesn’t already exist. To do that, we either have to add the element or use the .append method.
Arrays have a .count property which is an integer containing the number of elements in an array. To remove the last element of an array, we could get the count of an array, then call the .removeAtIndex() method, passing count – 1.
myFrogs.count // 4
myFrogs.removeAtIndex(myFrogs.count – 1) // “Bert”
myFrogs // [“Benny”, “Billy”, “Boris”]
But removing the first or last element of an array is a common operation, so Swift provides the .removeFirst() and removeLast() methods as well:
myFrogs.removeFirst() // “Benny”
myFrogs.removeLast() // “Boris”
myFrogs // [“Billy”]
We can check if an array has elements by using the count property: if count == 0, the array is empty. Swift also provides the .isEmpty boolean property which returns true only if the array contains no elements:
myFrogs.isEmpty // false
There are many other methods of the array collection, you should check them out in a playground by looking at the help when you type a . after the the array name.
In this screen, the icon at the left indicates whether the item is a method (M) or a property (V, for Value) of the object, the blue text shows the type of the property or the return type of the method, and the black text shows the name of the property or method. Here we can see that isEmpty is a value of Bool type. At the top, we see a short description of the method or property. For isEmpty, this is “Returns true iff self is empty.” The word “iff” here is not a typo, it’s programmer-speak for “if and only if.” We’ll explore the meaning of “self” later in this context.
Some of the types in blue will be unfamiliar to you, don’t worry about that, we’ll fill in the gaps as we go along. Reading this help information is a great way to learn about what properties and methods an object has.
There are two other ways to get context-sensitive help. Holding down the option key and clicking a symbol will bring up the documentation for that symbol. Below, we’ve option-clicked String to find out more about it:
We can also open the declarations for an object by holding down the Command key and clicking the object. This will probably be a bit overwhelming now, but later, as you learn more about Swift (and need to know more about iOS framework objects), these listings become very useful.
Back to arrays. The array declaration syntax we’ve been using so far is really syntactic sugar for something called a generic. Generics are a way to allow a single object to be declared with members of different types. We can have an array of Ints, or Doubles, or Tuples, or, well, anything really. We’ll learn how to implement our own generics later, but for now the key point is that Swift collections are all implemented as generic types.
The generic syntax declaration for a new empty array of Float called myScores looks like this:
var myScores = Array<Float>()
The type of myScores is Array. The array is composed of Floats; the angle brackets define the type we’ll be working with when we’re using the generic syntax. Finally, we’re calling the constructor for the Array, so we need the parentheses.
We can now add, index, and delete elements from this array just like any other (it’s the same type; it just uses the “real” generic syntax rather than the shorthand syntax).
myScores += [78, 93, 42.5] // [78, 93, 42.5]
myScores.append(83) // [78, 93, 42.5, 83]
myScores.removeAtIndex(1) // 93
myScores // [78, 42.5, 83]
Either syntax is fine to use in programs; they result in the same data structure. The shorthand syntax is more commonly used with arrays, however.
Strings and Characters in Swift15 Jun, 2016
Optionals in Swift09 Jun, 2016
Swift Integer Types02 Jun, 2016
Dictionaries in Swift16 Apr, 2016
Functions in Swift 225 May, 2015
Curried Functions In SWIFT13 May, 2015
Indexed Table Views In Swift07 May, 2015
Creating Grouped Table Views In Swift