ArraySlice In Swift
Array is a very common data collection. We use it pretty much every day. Array in Swift is very powerful and provides several features. In this article, we’ll discuss one of them: ArraySlice.
ArraySlice as “Views onto Arrays”. It means that an
ArraySlice is an object which represents a subsequence of its array. It’s very powerful and allows us to perform the same array operations on a slice like
map and so on.
In this article, we will see how to create it and some internal behaviors to avoid troubles.
How to create an
Before using an
ArraySlice, we must understand how to create it. Swift provides several ways to get a slice from a given array:
Array provides some methods to create a subsequence removing some elements. These methods are
If we want to create a subsequence with the first elements of a given array, we can use the method
suffix has the opposite behavior of
prefix. It returns the last elements of the array:
We can create an
ArraySlice using also a range of indices:
With Swift 4, we can omit the
startIndex if want to use the index 0 and the
endIndex if we want to use the last index of the array:
Let’s suppose that we want to remove the last 5 elements from an array. We can use the method
dropLast(5) and assign the result to the array:
Unfortunately, Swift doesn’t allow to assign an
ArraySlice object to an
Array. For this reason, in example above, we have a compile error
Cannot assign value of type 'ArraySlice<Int>' to type '[Int]'. We need a way to convert the
ArraySlice object to
Array. Fortunately, Swift allows us to cast the slice variable using the syntax
Array(<slice_variable>). We can use this cast to fix the example above like this:
ArraySlice and its
ArraySlice holds a strong reference of its array. It means that we should pay attention how we use the slice to avoid troubles with the memory. Apple added also a warning about it in the documentation:
Long-term storage of ArraySlice instances is discouraged. A slice holds a reference to the entire storage of a larger array, not just to the portion it presents, even after the original array’s lifetime ends. Long-term storage of a slice may therefore prolong the lifetime of elements that are no longer otherwise accessible, which can appear to be memory and object leakage.
We can test this behavior with the following example:
If we let run this example, we can notice that the property
slice holds a strong reference of the array elements. Even though
arrayHandler is destroyed at the end of the
init scope, the
deinit method of
Element is not called.
Let’s suppose that we have an
Array and an its
ArraySlice. If we change the elements of the
ArraySlice won’t be affected and will continue storing the original elements:
Vice versa, if we change the elements of an
Array won’t be affected:
ArraySlice maintains the same indices of its array. It means that the element at index 3 of an
ArraySlice is the same element at the index 3 of its original array.
Let’s consider an
ArraySlice with a range
2...4. If we try reading the element at index 0 of the slice, we would have a run time error:
It happens because the slice doesn’t contain the element at index 0 of the array but only the elements at index 2, 3 and 4.
If we want to get the first and last index of a slice in a safe way, we should use
endIndex returns the position one greater than the last valid index. For this reason, we must use
endIndex - 1 in the example above to avoid an
Index out of bounds error.
In addition to
ArraySlice, Swift provides also a base object Slice. It allows us to get a subsequence of other collection objects like
Set and any kind of custom collection.