Immutable/Mutable Collections in Swift
Arrays
Create immutable array
First way:
let array = NSArray(array: ["First","Second","Third"])
Second way:
let array = ["First","Second","Third"]
Create mutable array
var array = ["First","Second","Third"]
Append object to array
array.append("Forth")
Dictionaries
Create immutable dictionary
let dictionary = ["Item 1": "description", "Item 2": "description"]
Create mutable dictionary
var dictionary = ["Item 1": "description", "Item 2": "description"]
Append new pair to dictionary
dictionary["Item 3"] = "description"
More information on Apple Developer
How to change $0 to be mutable?
You don't need $0
to be mutable. map
will use whatever value you return, so you can use the last map like this:
.map {$0 == "123" ? "replace" : $0}
When that map
closure is run, whenever $0
matches "123"
, it will return replace
, otherwise it will return the current value.
How do you create an immutable array in Swift?
This has changed with Xcode 6 beta 3. While arrays used to be semi-mutable, as you describe, with their elements changeable but their length fixed, now immutable arrays share the same value semantics as Dictionaries:
From the Xcode 6 beta 3 release notes:
• Array in Swift has been completely redesigned to have full value semantics like Dictionary and String have always had in Swift. This resolves various mutability problems – now a 'let' array is completely immutable, and a 'var' array is completely mutable – composes properly with Dictionary and String, and solves other deeper problems. Value semantics may be surprising if you are used to NSArray or C arrays: a copy of the array now produces a full and independent copy of all of the elements using an efficient lazy copy implementation. This is a major change for Array, and there are still some performance issues to be addressed. Please
!see the Swift Programming Language for more information. (17192555)
The original information on arrays in the Swift book was updated on 7th July 2014 to reflect the beta 3 changes. (If you're using iBooks on a Mac, as I was, you may need to delete and re-download it to pick up the 7th July update—I couldn't get the thing to update automatically.)
How does let/var resolve mutability?
For arrays and dictionaries, the let
or var
keyword decides whether the whole collection would be mutable or immutable. In other words, if you declare a dictionary immutable by using the let
keyword, you cannot change any of its values, so the second example would not work.
In Swift
deciding whether a collection will be mutable or immutable only depends on the keyword you use to declare it, so declaring an array/dictionary using the let
keyword will be equivalent to declaring an immutable array (NSArray
in Objective-C) while declaring it with the var
keyword will give you a mutable array (NSMutableArray
in Objective-C).
Immutable `var` array
What you want doesn't make sense for Array
, because it is a value type with value semantics. The value of the variable is the array -- so the ability to change the variable and the ability to change the array are in a way the same thing.
Semantically there is no difference between:
myArr.append(42)
and something like (made up):
myArr = myArr.newArrayWithAppending(42)
In a way, you can imagine that any "modification" to a value type variable could be implemented as assigning a completely new value to the variable. (It's probably not done that way because it would be inefficient, but from a semantics point of view, there is no reason why it could not be implemented that way.)
The concept of "mutability" only makes sense for reference types, where the variable is a reference that points to the actual object, and the actual object can be shared between multiple references (so that "mutation" through one reference can be seen through another one).
With reference types, you can do what you want, with for example an immutable ImmutableArray
class, and then if you have a var
variable of type ImmutableArray
, then you can construct a whole new immutable array and change the variable to point to the new array, but any particular array object cannot be "changed" as seen from a shared reference.
Mutability in Swift
There is nothing to teach. Class instances are always mutable regardless of whether you say var
or let
.
Collections are structs; the rules you're describing are for structs, which are a different animal. They are almost classes in Swift, but not quite; you've put your finger on a key difference. Any struct you make will behave the same way: it will be immutable through a reference declared let
.
Making immutable function parameter mutable
You could either make that array available to all functions by declaring it as a property (and removing the class
modifier of your function) or you could define your function's parameter as an in-out parameter. By adding the inout
keyword right before the parameter's type, you can make the parameter mutable by keeping the reference to the passed array.
Nevertheless, I would recommend you to make your array into a property – simply because it's easier and, in my opinion, better maintainable.
How does one create a mutable copy of an immutable array in swift?
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)
Related Topics
How to Center a Popoverview in Swift
Swift Doesn't Convert Objective-C Nserror** to Throws
Instead of Push Segue How to Replace View Controller (Or Remove from Navigation Stack)
How to Open Mail App from Swift
Push Notification Not Receiving in Background iOS
Should I Declare Variables in Interface or Using Property in Objective-C Arc
Uitableview with Static Cells Does Not Appear
Swift - How to Detect Orientation Changes
Storing Images Locally on an iOS Device
Swift Default Alertviewcontroller Breaking Constraints
Trying to Compile the Ffmpeg Libraries for Iphoneos Platform with Armv6 and Arv7 Architecture
How to Reload Tableview from Another View Controller in Swift
Xcode 8 :Function Types Cannot Have Argument Label Breaking My Build