Присвоение значений свойствам в синглтоне, реализованным с помощью static let в 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"), возникает ошибка, когда я пытаюсь назначить gameScore и saveState.

ошибка игровой площадки не может быть присвоена свойству

Я использую 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

Можете ли вы объяснить, почему класс ссылочного типа лучше подходит для реализации синглтона, чем структура типа значения?


person Ben Morrow    schedule 09.09.2015    source источник
comment
я могу вам чем-нибудь помочь или вы в порядке?   -  person Korpel    schedule 10.09.2015
comment
Ваш ответ имеет смысл. Я должен был понять, почему я не должен реализовывать синглтон как структуру. Спасибо за вашу помощь :)   -  person Ben Morrow    schedule 13.09.2015


Ответы (1)


Вы не можете изменить его, потому что в вашей структуре есть константа let с именем defaultManager. Как вы уже знаете, структура — это тип копирования, а класс — это передача по ссылке. если вы хотите использовать его как структуру, вам придется вместо этого заменить let на var. Другой подход к этой проблеме — изменить структуру на class, чтобы вы могли изменить значение defaultManager, хотя оно объявлено как let.

ваше здоровье

edit: Основное отличие в вашем коде заключается в том, что когда у вас есть константа в class, и вы меняете эту константу, вы фактически ссылаетесь на ее адрес, а не на ее фактическое значение. То же самое не происходит с причиной struct в качестве типа значения, которое вы не может сделать этот вызов по ссылке, что вы делаете с class, и поэтому вы вынуждены иметь постоянное (let) значение, которое не может быть изменено. Измените let на var внутри вашего struct и посмотрите, как произойдет волшебство.

person Korpel    schedule 09.09.2015