Introduction

Apple describes 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 append, map and so on.

In this article, we will see how to create it and some internal behaviors to avoid troubles.

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:

1

2

3

4

5

vararray=[5,2,10,1,0,100,46,99]

letslice=array.dropLast(5)

array=Array(slice)// [5, 2, 10]

Relation between ArraySlice and its Array

Strong reference

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.

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.

Consequences of ArraySlice and Array changes

Let’s suppose that we have an Array and an its ArraySlice. If we change the elements of the Array, the ArraySlice won’t be affected and will continue storing the original elements:

1

2

3

4

5

6

7

vararray=[10,46,99]

letslice=array.dropLast()// ArraySlice<Int> [10, 46]

array.append(333)// [10, 46, 99, 333]

// `slice` is not affected and continues storing the original elements

print(slice)// ArraySlice<Int> [10, 46]

Vice versa, if we change the elements of an ArraySlice, its Array won’t be affected:

1

2

3

4

5

6

7

letarray=[10,46,99]

varslice=array.dropLast()// ArraySlice<Int> [10, 46]

slice.append(333)// ArraySlice<Int> [10, 46, 333]

// `array` is not affected and continues storing the original elements

print(array)// [10, 46, 99]

Slice Indices

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:

1

2

3

4

5

letarray=[10,46,99,00,6]

varslice=array[2...4]// ArraySlice<Int> [99, 0, 6]

slice[0]// fatal error: Index out of bounds

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 startIndex and endIndex:

1

2

3

4

5

6

letarray=[10,46,99,00,6]

varslice=array[2...4]// ArraySlice<Int> [99, 0, 6]

slice[slice.startIndex]// 99

slice[slice.endIndex-1]// 6

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.

Conclusion

In addition to ArraySlice, Swift provides also a base object Slice. It allows us to get a subsequence of other collection objects like Dictionary, Set and any kind of custom collection.

Share this:

Related

Marco Santarossa

Hi there, I'm Marco and I'm an Italian developer. I moved to London in 2016 to work at Sky as iOS developer.
I've been an iOS Developer since 2011 and I sometimes write embarrassing PHP/JS code.
I'm keen to learn new things and I spend most of my spare time learning as self-taught.
When I don't develop, I like watching MMA fights and cooking Italian food.