我是否应该使用var或let for对象稍后进行变异?

时间:2015-10-18 20:11:24

标签: ios swift variables constants

我有一个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 = ...。但是,如果我这样做,它会在以后变得不变吗?

感谢您的回答。

2 个答案:

答案 0 :(得分:3)

编译器实际上非常擅长决定是否应该使用letvar,在这种情况下,它是正确的。

应该在数据发生变异的任何地方使用

var。例如:

  • 属性将被突变的结构值
  • 指针(如您的COpaquePointer)
  • 将重新分配给不同类实例的类的实例
在数据不会发生变异的任何地方都应该使用

let。例如:

  • 常量
  • 要添加到数组,字典,函数参数等的值
  • 不会重新分配实例的类实例。

请注意,对于类的实例,即使将其定义为let,您仍可以修改该类的属性。只有在重新分配类本身时才应使用var

对于newProfile变量,在其生命周期内,它永远不会发生变异。创建对象,然后立即将其附加到数组中。该数组需要使用var进行定义,因为它使用append进行了变异,但newProfile永远不会被更改。如果您愿意,可以在以后更改从newProfile附加到数组的值,因为patientProfiles数组是可变的。

当您不确定是否使用letvar时,最佳做法是从let开始,看看编译器是否抱怨。如果是,请将其更改为var

答案 1 :(得分:1)

我发现你并不完全了解什么是常量以及它如何与值和引用类型一起使用。

您可以将常量视为带锁和钥匙的玻璃盒。

一旦你把东西放进盒子并锁定它,你就扔掉了钥匙,这样你就可以看到盒子内容(读取属性并调用非变异方法)但不能改变它。

单词 mutated immutable 只能应用于值类型,因为在值类型的情况下,该框本身保存值,如果某个值的方法可以更改值,那么它必须使用关键字mutating进行标记,以便通过方框玻璃看不到它。

如果是引用类型,则该框保存对类型实例的引用。如果您定义引用类型的常量,那么您有参考框。您无法更改引用,但您可以阅读它,然后通过该引用查找实例并使用该实例执行任何您喜欢的操作。

在您的情况下,您定义常量:

let newProfile = DBProfile(...)

DBProfile是类(引用类型)。 您无法为newProfile分配另一个引用,但您可以使用newProfile引用的对象执行任何操作。所以你将它附加到patientProfiles数组,你可以稍后从这个数组中获取它并做你想做的事。