Reputation: 4600
I have an iOS app that, upon startup, loads objects from persistent storage that will be manipulated later in the app. For example, on startup it loads patient profiles in an array. Does it matter if I define the items I add to the array as variables, versus constants, if they will be modified by the app later (say in a different View Controller)?
In my App Delegate, I load them like this:
func loadProfiles() {
var profileRecord: COpaquePointer = nil
if sqlite3_prepare_v2(db, "SELECT profilesid, objectSyncStatus, profileName, profileRelationship, profileFName, profileLName, profileAddress, profileCity, profileState, profileZip FROM profiles", -1, &profileRecord, nil) == SQLITE_OK {
if sqlite3_step(profileRecord) == SQLITE_ROW {
// Load profile stubs for each person
var newProfile = DBProfile(withDatabase: db, fromRecord: profileRecord, withLanguage: appLanguage, loadAllData: false)
patientProfiles.append(newProfile)
}
}
}
Of course, I get a warning that newProfile
is not mutated, and it wants to change it to let newProfile = ...
before it is added to the array. But, if I do that, will it become immutable later?
Thanks for the answers.
Upvotes: 2
Views: 124
Reputation: 1647
The compiler is actually really good at determining whether you should use let
or var
, and in this case, it is correct.
var
should be used anywhere the data will be mutated. For example:
let
should be used anywhere the data will not be mutated. For example:
Note that for instances of classes, you can still modify the properties of the class even if it is defined as let
. var
should only be used in this case when the class itself will be reassigned.
In the case of your newProfile
variable, during it's lifetime it is never mutated. The object is created, then immediately appended to your array. That array needs to be defined with var
because it is mutated with that append
, but newProfile
never gets changed. You can change the value that was appended from newProfile
through the array at a later date if you'd like because the patientProfiles
array is mutable.
A good practice for when you are not sure whether to use let
or var
is to start with let
and see if the compiler complains. If it does, then change it to var
.
Upvotes: 3
Reputation: 25846
I see that you do not quite understand what is constant and how it works with value and reference types.
You can think of constant as glass box with lock and key.
Once you put something in box and lock it you threw away the key so you can see box contents (read properties and call non-mutating methods) but can not change it.
Words mutated and immutable can be only applied to value types because in case of value type the box holds value itself and if some method of value can change value then it must be marked with keyword mutating
so it will not be visible through box glass.
In case of reference type the box holds reference to instance of type. If you define constant of reference type then you have box with reference. You can not change the reference, but you can read it and then go and find instance by that reference and do whatever you like with that instance.
In your case you define constant:
let newProfile = DBProfile(...)
and DBProfile
is class (reference type).
You can not assign another reference to newProfile
but you do whatever you like with object that referenced by newProfile
. So you append it to patientProfiles
array and you can get it later from this array and do what you want.
Upvotes: 1