Adding object to let constant NSMutableDictionary works, but why?

115 views Asked by At

I've been trying to figure out why it's possible to add objects to a let constant dictionary, but cannot find the answer.

The code below works, but I've always thought of let constants as immutable objects.

Anyone that can shed som light on this?

        // Create dictionary to allow for later addition of data
    let data: NSMutableDictionary = ([
        "firstname" : "john",
        "lastname" : "doe"
    ])

    // Add email to dictionary if e-mail is not empty
    if email != "" {
        data.setValue(email, forKey: "email")
    }
1

There are 1 answers

1
Ryan H. On BEST ANSWER

In Swift the let keyword is used to declare a constant. However, there are some things you need to be aware of depending on if you are declaring a constant for a reference type or a value type.

Reference Type

// Declare a class (which is a reference type)
class Foo {
    var x = 1
}

// foo's reference is a constant. 
// The properties are not unless they are themselves declared as constants.
let foo = Foo()

// This is fine, we are not changing the foo reference.
foo.x = 2

// This would result in a compiler error as we cannot change 
// the reference since foo was declared as a constant.
foo = Foo()

Value Type

// Declare a struct (which is a value type)
struct Bar {
    var y = 1 // Note the var
}

// bar's value is a constant. The constant nature of the value type properties 
// that are part of this value are subject to bar's declaration.
let bar = Bar()

// This would result in a compiler error as we cannot change 
// the value of bar.
bar.y = 2

Mixture of Reference and Value Types

Generally you wouldn't want to have a reference type property defined on a value type. This is for illustrative purposes.

// Declare a struct (which is a value type)
struct Car {
    let foo = Foo() // This a reference type
}

// The value is a constant. But in this case since the property foo 
// is declared as a constant reference type, then the reference itself 
// is immutable but its x property is mutable since its declared as a var.
let car = Car()

// This is fine. The x property on the foo reference type is mutable.
car.foo.x = 2

Since NSMutableDictionary is a class, declaring the reference as a constant ensures you cannot change its reference, however its mutable properties can be changed.

The comment on your question from @vadian regarding NSMutableDictionary should be noted.