Arrays are a very common component in many programming languages. Swift is no different. Arrays are an ordered list of objects of the same type in Swift. This is the case for arrays in most other programming languages, but Objective-C’s NSArray was capable of holding values of different types in the same NSArray. In that case, they were stored as id, and thus took a bit more work to change them back into whatever type they actually were. Swift simplifies it by enforcing that all values are of the same type. This in particular makes things safer, so you don’t have to check what type a variable is when you take it out of a Swift array.
Swift Array Command Quick Reference
Below I have included a simple table that will show the major functions and operators for Arrays, and we will go a bit more in depth with them afterwards:
Title | Example | Description |
Array Shorthand Type | [Int] | This is used when explicitly declaring the type of the array. This example is a type for an array of Ints. |
Array Literals | [1, 3, 7, 12, 40] | This is a shorthand way to generate an array of known objects. They must all be of the same type. |
Initialize Empty Array | [Int]() | This initializes an empty array of type Int. |
Initialize With Repeating Value | [Int](repeating: 40, count: 7) | This initializes an integer array with 7 elements, each at a value of 40. |
Subscript Syntax | someArray[0] | The standard way to retrieve a value from an array. This example retrieves the 1st object (at index 0) |
First Element Shorthand | someArray.first | This returns an optional containing the first value in the array, or nil if the array is empty. |
Last Element Shorthand | someArray.last | This returns an optional containing the last value in the array, or nil if the array is empty. |
Number of Elements | someArray.count | This returns an Int of how many values are in the array. |
isEmpty Shorthand | someArray.isEmpty | This returns a Bool describing whether the array is empty or not. If count is 0, this returns true, otherwise it will return false. |
Append to Array | someArray.append(5) | This appends a new element containing the Int 5 to our Int array. |
Append Shorthands | someArray+=[5] | Shorthand for above. The value must stored in an array itself, even if it contains only 1 element like this example. |
Insert Value at Index | someArray.insert(42, at: 3) | This will insert a value of 42 into the array at index 3. |
Remove Value at Index | someArray.remove(at: 2) | This will remove the value at index 2. It will return that value, but it can be ignored if you only wanted to remove it. |
Remove at End of Array | someArray.removeLast() | Same as above for the last element in the array. Makes checking array upper bound unnecessary for final value. |
Remove All Values | someArray.removeAll() | Removes all values from array. Can take a Bool for keepCapacity to not change capacity value. If omitted, defaults to false and sets capacity to 0. |
Add Array | someArray + anotherArray | This returns a new array that contains the elements of someArray first, followed by the elements of anotherArray afterwards. |
Reverse Array | someArray.reversed() | This returns an array that has all elements in the reverse order from source array. |
There are several more, but these are some of the most important. I’m not sure I would use the reverse method very often, but I’m glad it’s there.
Creating Arrays
Like other built in types to Swift, there are two major ways to create arrays, with a literal or an initializer. An example of how to create Int arrays with each are shown below:
let literalArray = [0,1,1,2,3,5,8,13,21] var emptyArray = [Int]() let defaultValueArray = [Int](repeating: 0, count: 5)
The third one is also an initializer, but it lets you create an array with a certain number of elements with an initial value set. In this case, it creates the equivalent of the literal [0,0,0,0,0], an array of 5 Integers, all set to 0.
The [Int] is actually shorthand for the full form of an Array of type Int: Array<Int>. This was not listed in the quick reference, because while it is how it is created under the hood, Apple encourages using the shorthand due to its increased readability.
Does something look a bit familiar with that type? It is using generics! Generic types are similar to generic functions, but they are types that are generalized to take in different types of values. They are most often used with collection types, including arrays of course, but also Dictionaries. The example in Apple’s iBook uses a stack, another type of collection, to show how they work and are created. If you want to learn more, check out my post on Generic Types in Swift. You can also learn a bit more about Generics from an earlier post Generic Functions in Swift.
One thing to note, arrays act a little differently depending on how they are stored. An array stored as a var is completely mutable. You can change it, append or remove objects however you want. An array stored as a let constant is completely immutable. You can read from it, but you cannot change anything.
Accessing Array Values
There are several ways to read values from your array in Swift. The first, and most standard way, is via subscript syntax:
let fourthValueOfArray = literalArray[3]
As the variable name says, this reads the fourth value of literalArray. In C, and most other languages, arrays count up from 0, so that is why the fourth value is at index 3. This may be made more obvious by a small chart:
index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
literalArray Value | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 |
You can see that the fourth element is index 3, and contains the number 2.
There are also a few shortcuts to read certain elements of an Array in Swift. To read the first and last values of an array in most languages you would have to manually set it to an array bound. That is easy for the first one, that’s just [0], but the last one, that usually required something like [literalArray.count – 1] in many other languages. Yeah, it works, but it is not very succinct. Apple decided to add some nice shortcuts to these that made it a lot more obvious what you’re doing, and just make the code look cleaner. They added the first and last computed properties:
let firstValue = literalArray.first //Returns Optional Int containing 0 let lastValue = literalArray.last //Returns Optional Int containing 21
These return optional values of the type of the array that contain the first and last values of the array respectively. Why an optional? Well, what is the first or last value of the emptyArray we made earlier? If the array is empty, this returns a nil, otherwise, it will return an optional containing first or last value. Even if the array only has 1 element, it will still return an optional containing the first and last value, which happen to be the same index in that case. You will have to optionally bind, or otherwise somehow unwrap the value to get back the initial Int, like you have to with most optionals. You can learn more about optionals from my post Swift Optionals – Declaration, Unwrapping, and Binding.
One other way to get values from an array, if you want to go through all of them, is with a for-loop. You can use a normal for loop and set the ranges manually, or you can use the for-in loop.
var sum = 0 for number in literalArray { sum += number }
This small snippet adds each of the numbers together from our literal array by iterating over them an just adding them to the value of sum. You can read more about the for-in loop from my post Loops, Switch Statements, and Ranges in Swift.
When I learned about the foreach loop in C# (the equivalent of the Swift for-in loop), I started using it everywhere, but then I would sometimes run into an issue. I would want to step through something but would sometimes need the index. Swift has given that capability here with the magic of tuples and the enumerate method.
for (index, number) in literalArray.enumerated() { print("Fibonacci Number \(index): \(number)") } //Last Line Output: "Fibonacci Number 8: 21"
That prints out 9 lines describing the numbers listed in literalArray, which were the Fibonacci numbers. I didn’t want to clutter this further with all 9 lines, but I included the last one above. The enumerate in that for-in loop is a global function that returns a tuple composed of the index and value of what it is enumerating through. If you want to learn more about Tuples, check out my post Tuples in Swift: Create, Read, and Return.
Number of Elements in an Array
There are a couple ways to check how many elements are in the array. The simple one is the count command. It will return an Int containing how many values are in the array:
let elementsInArray = literalArray.count //returns 9
That’s simple enough. Now, if you want to check if you have any values, sure you could compare if the count is greater than 0, or you could just ask the array if it is empty:
let emptyStatus = literalArray.isEmpty //returns false
That just returns a boolean describing whether the array is empty. If the count is above 0, it returns true, otherwise it returns false.
Mutating an Array
For mutable arrays (arrays created as a var), you have several different ways to mutate arrays
Adding to the Array
You can append to the end of an array, or insert a value at a certain index. To append, you can use the append command, or the shorthand += operator, as shown below:
emptyArray.append(5) emptyArray += [5]
Those two statements are functionally equivalent for this task. One thing to note, to use the += operator, you must actually have an array on the righthand side, even if it is only of one value. The extra part about that though, is that if you want to add more than one value, you just add to that array literal, so you could add more values to the array like this:
emptyArray += [9, 8, 7, 6]
Now the (now inappropriately named) emptyArray contains [5, 5, 9, 8, 7, 6] (since we added two 5s to it earlier).
You can insert a value at an arbitrary place as well with the insert command, like this:
emptyArray.insert(12, at: 2) //emptyArray now is [5, 5, 12, 9, 8, 7, 6]
We inserted the value 12 at index 2. This shifted the former index of 2, and everything above it up by one, and put the value we wanted at index 2.
Removing from the Array
You can also remove from the array as well. We can remove from a specific index if we want:
let valueThatWasRemoved = emptyArray.remove(at: 3) //emptyArray now is [5, 5, 12, 8, 7, 6]
We removed that 9 that was at index 3 with the remove(at: command. It also has the added ability to return the value that was removed, which we stored in valueThatWasRemoved. This can be ignored and not stored if you just wanted to remove the value. This is obviously the inverse of the insert:atIndex: command.
The inverse of the append command is the removeLast command, as shown below:
let formerlyLastValue = emptyArray.removeLast() //emptyArray now is [5, 5, 12, 8, 7]
Like the removeAtIndex command, this also returns its value, which we stored in the formerlyLastValue variable.
Wasn’t this emptyArray supposed to be an empty array? Lets just get rid of all of this:
emptyArray.removeAll() //emptyArray now is empty once more
This method actually takes an argument on whether you want to keep the capacity or not as it was (so it won’t need to reallocate memory if you plan on refilling it soon). If omitted (like above), it defaults to false, and sets the capacity back to zero. If you did want to keep the capacity, you would use the method like this:
let originalCapacity = emptyArray.capacity //originalCapacity = 6 emptyArray.removeAll(keepCapacity: true) let newCapacity = emptyArray.capacity //newCapacity = 6
This was for emptyArray when it had the values [5, 5, 12, 8, 7], so it could apparently store 6 values before reallocation. For removeAll() with no parameters, the newCapacity would equal 0.
Create new Arrays based on Previous ones
You can combine two arrays by simply using the + operator. It returns a new array that puts the elements on the left-hand side first, and the elements on the right-hand side afterwards.
var arrayOne = [1, 2, 3, 4, 5] var arrayTwo = [30, 40, 50] var bothArrays = arrayOne + arrayTwo //bothArrays now is 1, 2, 3, 4, 5, 30, 40, 50]
If you really want, you can even have the reverse-ordered form of the array returned as a new array as well with the aptly named reverse command:
let normalArray = [20, 21, 22, 23, 24, 25] let reversedArray = normalArray.reversed() //reversedArray now is [25, 24, 23, 22, 21, 20]
I’m not sure when I’d use it, but it’s still good that it’s there. The reason why reversedArray was explicitly typed as an array is that if not, the type inference actually creates it as a ReversedCollection<[Int]> type, which also is a CollectionType like Array, that apparently handles the reverse itself. When reversedArray is explicitly typed, it lets you see its result again as an Array.
Conclusion
We’ve covered many methods that can be performed on arrays. There is one particularly important one, named map, but we will cover that one another time. The map method performs a block of code to each element of an array, which is called a closure. You can check out my post about Closure Expressions in Swift., to learn more about the map method and other information about Closures.
I hope you found this article helpful. If you did, please don’t hesitate to share this post on Twitter or your social media of choice, every share helps. Of course, if you have any questions, don’t hesitate to contact me on the Contact Page, or on Twitter @CodingExplorer, and I’ll see what I can do. Thanks!