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

Ben*_*row 3 singleton value-type reference-type 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
Run Code Online (Sandbox Code Playgroud)

因为被声明为常量(使用“let”),所以当我尝试分配和defaultManager时会出现错误。gameScoresaveState

游乐场错误无法分配给属性

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

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


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

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
Run Code Online (Sandbox Code Playgroud)

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

Kor*_*pel 5

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

干杯

编辑:代码中的主要区别在于,当您在 a 中有一个常量class并且更改该常量时,您实际上引用的是它的地址而不是它的实际值。struct作为值类型的原因不会发生同样的情况,您可以'不要通过引用来调用你所做的事情class,因此你被迫拥有一个let不能改变的constant()值。将 更改letvar您的内部struct,看看奇迹发生