Reputation: 17732
I have a simple custom class that for the sake of simplicity in the example lets say it contains a single property that is an array of arrays of strings. It has a single method that moves the first object from one array to another. Ignore the missing initializer, this is a truncated version of an existing class I've written.
class MyClass: NSObject
{
var strings:Array< Array< String > >
func makeMove(fromArray:Int, toArray:Int)
{
var from = strings[fromArray] as Array< String >
var to = strings[toArray]
let top = from[0]
to.append(top)
from.removeAtIndex(0)
towers[fromTower] = from
towers[toTower] = to
}
}
If I declare a new instance of MyClass
and call this single method on it, I get a compiler warning stating that the instance was never modified and should be made a let
instead of var
.
var myInstance = MyClass() //Warning
myInstance.makeMove(0, toArray:1)
let myInstance = MyClass() //No warning
myInstance.makeMove(0, toArray:1)
Interestingly enough, even though in the second instance it is a let
, which should be a constant, the instance does in fact get mutated when makeMove
is called on it.
Whats wrong in this case? Should I use a let
, or is the compiler not properly recognizing that it is a mutating function?
Upvotes: 2
Views: 1907
Reputation: 14973
To conclude, here is what I think you want, with a suggestion from wjl:
class MyClass {
var strings : [[String]] = []
func makeMove(fromArray from: Int, toArray to: Int) {
let item = strings[from].removeAtIndex(0)
strings[to].append(item)
}
}
let a = MyClass()
a.strings = [["Hi", "H", "A", "C"], ["He", "Ab", "To", "Hehe"]]
a.makeMove(fromArray: 0, toArray: 1)
a.strings // [["H", "A", "C"], ["He", "Ab", "To", "Hehe", "Hi"]]
// a = MyClass() // error: cannot assign to value: 'a' is a 'let' constant
You can still change that instance of the object, but you cannot change the object, a
is pointing to
Upvotes: 0
Reputation: 8718
First of all, make sure you understand reference types versus value types.
https://developer.apple.com/swift/blog/?id=10
The let
keyword prevents mutation to the latter, not the former. Think of a let
reference variable as: the reference (memory address) that the variable refers to cannot change, but the contents of that memory can.
So the warning is trying to tell you that you never re-assign the reference myInstance
to another object, but your declaration allows for the possibility.
If your design is such that myInstance
should always refer to the object it was first assigned to, let the compiler help you by denoting it as let
. Then feel free to pass the reference around and change the object's contents as needed using any copy of the reference.
Upvotes: 2