Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one create a mutable copy of an immutable array in swift?

Tags:

Now that Swift's Array's are truly immutable thanks to full value semantics, how can I create an mutable copy of an immutable array? Similar to Obj-C mutableCopy(). I can of course downcast the array to an NSArray and use mutableCopy() but don't want to use NSArray because it does not strictly typed.

I have a toolbar which has items from the storyboard. I want to remove an item from the toolbar and use toolbar.setItems. I wanted to do it without casting as a NSArray, because none of these functions take NSArrays, they take [AnyObject].

Obviously now when I call removeAtIndex() it does not work, which is correct. I just need a mutableCopy

Simply assigning to var does not work for me and give 'Immutable value of type [AnyObject]'

var toolbarItems = self.toolbar.items
toolbarItems.removeAtIndex(2) //Immutable value of type [AnyObject]

I am using Beta 3

like image 603
Johnston Avatar asked Jul 13 '14 10:07

Johnston


2 Answers

The problem is that self.toolbar.items is an implicitly unwrapped optional (of type [AnyObject]!) and they are always immutable. When you assign to the variable toolbarItems without explicitly stating its type, it too becomes an implicitly unwrapped optional, and thus is immutable as well.

To fix this do either:

var toolbarItems:[AnyObject] = self.toolbar.items
toolbarItems.removeAtIndex(2)

Or:

var toolbarItems = self.toolbar.items as [AnyObject]
toolbarItems.removeAtIndex(2)

Update

As of Xcode 6 Beta 5, you can update collections that are stored in optional variables, so the original code now works:

var toolbarItems = self.toolbar.items
toolbarItems.removeAtIndex(2)
like image 83
vacawama Avatar answered Oct 27 '22 05:10

vacawama


Arrays are value types (struct), so they are passed around by value and not by reference.

That said, if you create a variable of array type and assign it the immutable array, a copy of the immutable array is actually created and assigned to it - and of course that copy has no relationship with the original immutable array (besides having the same values at the time it is created).

let immutable = [1, 2, 3]

//immutable[0] = 1 // Fails, ok

var mutable = immutable

mutable[0] = 5

In your case, you are accessing an immutable array which is an NSArray of AnyObjects (see documentation). You can use it as an Array in swift, make a copy of it and modify as follows:

let immutable : NSArray = [ 1, 2, 3 ]

//immutable[0] = 1 // Fails, ok

var mutable : [AnyObject] = immutable

mutable.removeAtIndex(1) // mutable now is [1, 3]

mutable[0] = 7 // mutable now is [7, 3]

After you're done with your changes, you can assign to the items property

like image 23
Antonio Avatar answered Oct 27 '22 03:10

Antonio