Стремительный синглтон или глобальная переменная - или что-то еще? - PullRequest
0 голосов
/ 05 ноября 2018

Я программирую настольную игру. Есть пара экранов и множество функций. Мне часто нужно изменить какую-то переменную, например, «деньги» или «дерево». Я добавил «didset», чтобы я мог обновить вид, отображающий сумму денег.

Я вижу два варианта для этого. Либо глобальная переменная

var money = 0 {didSet {NotificationCenter.default.post(name: NSNotification.Name(rawValue: "showMoney"), object: nil)}}

или синглтон

class resources {

static let shared = resources()

var money = 0 {didSet {NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ResourcenAnzeigen"), object: nil)}}

private init() {}

}

Теперь я читаю, что синглтоны всегда предпочтительнее, чем глобальные. Но мне интересно, почему. В моем примере оба, кажется, делают то же самое. Разница лишь в том, что я должен написать

money += 1

или

resources.shared.money += 1

Первый выглядит проще.

И есть ли третий способ получше? Я прочитал, что можно передать необходимые переменные каждой функции или viewcontroller - но это выглядит для меня как лишний лишний код?

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

На самом деле Singleton - это особый случай глобальной переменной. Доступ к глобальному экземпляру Singleton просто затенен. Это помогает поддерживать чистоту глобального пространства имен.

Но синглтон НЕ ДОЛЖЕН использоваться для глобального доступа. В iOS Singletons используются для уникальных ресурсов , таких как файловая система , сети , пользовательских данных и т. Д.

Я предлагаю вам создать экземпляр в корне вашего приложения и внедрить его там, где вам это нужно. Это также облегчает тестирование и сохраняет ваш код в чистоте. Там вы также можете использовать шаблон наблюдателя, чтобы избежать глобального NotificationCenter.

К вашему сведению: Шаблоны связи

0 голосов
/ 05 ноября 2018

Синглтон будет правильным способом.

Основная проблема с использованием глобальной переменной вместо синглтона для этих целей заключается в том, что в случае, если у вас есть локальная переменная money в каком-либо другом объекте, компилятор не сможет неявно определить, какие деньги вы ссылались к.

Итак, если вы решите добавить деньги в качестве переменной в каком-то другом месте и попытаетесь обновить эту глобальную money переменную внутри того же самого, это закончится до изменения вашей локальной переменной, и не будет обновлять вашу глобальную переменную.

Но если вы используете одноэлементное свойство для установки или получения такого свойства, вы будете в безопасности от этой ситуации.

var money = 0

class MyClass {

    var money = 0

    func doSomethingAndIncrementGlobalMoney() {
        money += 1
    }
}

print(money)   // Prints 0

let myObject = MyClass()
myObject.doSomethingAndIncrementGlobalMoney()

print(money)   // Prints 0, while the expectation was to increment the global 'money' by 1.

Или, вы можете просто использовать что-то вроде:

struct MyGlobalItems {
    static var money: Int = 0
}

// Using the variable:
MyGlobalItems.money += 1
...