在 Swift 中使用 static let 实现的单例中为属性赋值

Assigning values to properties in a singleton implemented with static let in Swift

从阅读来看,在 Swift 中创建单例的最佳建议似乎是像这样使用 static let

struct GameManager {
  static let defaultManager = GameManager()
  var gameScore = 0
  var saveState = 0
  private init() {}
}

GameManager.defaultManager.gameScore = 1024 // Error
GameManager.defaultManager.saveState = 12 // Error
let score = GameManager.defaultManager.gameScore
let savedProgress = GameManager.defaultManager.saveState

因为 defaultManager 被声明为常量("let"),当我尝试分配 gameScoresaveState.[=19 时出现错误=]

我是 运行 Xcode 7.0 beta 6 (7A192o) 和 Swift 2.0 (swiftlang-700.0.57.3 clang-700.0.72)。

如果我将 defaultManager 更改为声明为变量(使用 "var"),它是否不再被视为正确的单例?


如果我将 GameManager 更改为声明为 class 而不是结构,那么代码将按预期工作。

class GameManager {
  static let defaultManager = GameManager()
  var gameScore = 0
  var saveState = 0
  private init() {}
}

GameManager.defaultManager.gameScore = 1024 // No error, why?
GameManager.defaultManager.saveState = 12 // No error, why?
let score = GameManager.defaultManager.gameScore // 1,024
let savedProgress = GameManager.defaultManager.saveState // 12

你能解释一下为什么引用类型 class 比值类型结构更适合实现单例吗?

您无法真正更改它,因为在您的结构中有一个名为 defaultManagerlet 常量。如您所知,结构是一种复制类型,而 class 是引用传递类型。如果您想将其用作结构,则必须将 let 替换为 var。这个问题的另一种做法是将结构更改为 class 这样您就可以更改 defaultManager 值,尽管它被声明为 let.

干杯

编辑:代码的主要区别在于,当您在 class 中有一个常量并且您更改该常量时,您实际上指的是它的地址而不是它的实际 value.Same struct 不会发生,因为作为值类型你不能通过引用调用你用 class 做的事情所以你被迫有一个常量(let)值不能突变。将 struct 中的 let 更改为 var 并看到奇迹发生