I recently came across this question on Twitter:
Hey #swiftlang peeps: How do you create an var that holds an immutable Array? As in a var that you can assign different immutable Arrays to?
— Mike R. Manzano (@bffmike) October 17, 2014
This is an interesting question. As a developer coming from Objective-C and the Cocoa frameworks, we’re used to distinguishing between NSArray
and NSMutableArray
. It’s generally bad practice to expose an NSMutableArray
as a public property on an object.
The problem is that another part of the app could modify the contents of the pizzaMenu
array without the knowledge of the Pizzeria
object. The Pizzeria
still points to the same object it always has; from its perspective, nothing has changed. This is bad.
Instead, a better practice is to only expose an immutable NSArray
. This way, whenever any change happens, the setter method will be called. The Pizzeria
is always aware of what’s happening.
Array
type is built into the language. Though you can still use NSArray
and NSMutableArray
, it’s often not necessary; the native Array type is plenty capable.Pizzeria
object and external code referenced the same object, so we had to expose an NSArray
that does not have APIs for changing its contents.CGRect
variables have the same value, it simply means that the two rects contain the same data. A change to one rect will never change the value of another rect stored in a separate variable.struct
s can have methods just like class
es can. Swift’s built-in collections (Array
and Dictionary
) are value types.Array
never affects any other variable, anywhere.pizzeria.pizzaMenu
is a mutable var
property, modifying the array we get back from the pizzeria has no effect on the pizzeria’s copy of the data. They are separate arrays, separate values, and we can’t change their copy unless we go through the setter.obj.someInts.append(1)
causes a new value to be constructed, which is then assigned back into the someInts
property!NSArray
and NSMutableArray
necessary in the first place. If you need a shared array, you can still use the Cocoa types. In every other case, Swift’s solution is safer, simpler, and more concise.mutating
if they’re going to modify any data. Otherwise, they cannot be called on a value stored in a let
variable. ↩
Leave a Reply