我有一个iOS应用程序,在启动时,从持久存储中加载对象,稍后将在应用程序中进行操作。例如,在启动时,它会加载阵列中的患者配置文件。如果我将我添加到数组中的项目定义为变量,而不是常量,如果它们稍后会被应用程序修改(比如在不同的View Controller中),这是否重要?
在我的App Delegate中,我加载它们:
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)
}
}
}
当然,我收到警告newProfile
未发生变异,并希望在将其添加到数组之前将其更改为let newProfile = ...
。但是,如果我这样做,它会在以后变得不变吗?
感谢您的回答。
答案 0 :(得分:3)
编译器实际上非常擅长决定是否应该使用let
或var
,在这种情况下,它是正确的。
var
。例如:
let
。例如:
请注意,对于类的实例,即使将其定义为let
,您仍可以修改该类的属性。只有在重新分配类本身时才应使用var
。
对于newProfile
变量,在其生命周期内,它永远不会发生变异。创建对象,然后立即将其附加到数组中。该数组需要使用var
进行定义,因为它使用append
进行了变异,但newProfile
永远不会被更改。如果您愿意,可以在以后更改从newProfile
附加到数组的值,因为patientProfiles
数组是可变的。
当您不确定是否使用let
或var
时,最佳做法是从let
开始,看看编译器是否抱怨。如果是,请将其更改为var
。
答案 1 :(得分:1)
我发现你并不完全了解什么是常量以及它如何与值和引用类型一起使用。
您可以将常量视为带锁和钥匙的玻璃盒。
一旦你把东西放进盒子并锁定它,你就扔掉了钥匙,这样你就可以看到盒子内容(读取属性并调用非变异方法)但不能改变它。
单词 mutated 和 immutable 只能应用于值类型,因为在值类型的情况下,该框本身保存值,如果某个值的方法可以更改值,那么它必须使用关键字mutating
进行标记,以便通过方框玻璃看不到它。
如果是引用类型,则该框保存对类型实例的引用。如果您定义引用类型的常量,那么您有参考框。您无法更改引用,但您可以阅读它,然后通过该引用查找实例并使用该实例执行任何您喜欢的操作。
在您的情况下,您定义常量:
let newProfile = DBProfile(...)
和DBProfile
是类(引用类型)。
您无法为newProfile
分配另一个引用,但您可以使用newProfile
引用的对象执行任何操作。所以你将它附加到patientProfiles
数组,你可以稍后从这个数组中获取它并做你想做的事。