Andy
Andy

Reputation: 193

Swift singleton or global variable - or something else?

I am programming a board game. There are a couple of screen and many functions. I often need to change some variable like "money" or "wood". I added "didset" so I can update a View that displays the amount of money.

I see two options for this. Either a global variable

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

or a singleton

class resources {

static let shared = resources()

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

private init() {}

}

Now I read singletons are always preferred instead of globals. But I wonder why. In my example both seem to do the same. The only difference is I either have to write

money += 1

or

resources.shared.money += 1

The first one looks easier.

And is there a third better way? I read one could give over the needed variables to every function or viewcontroller - but that looks to me like much unneccessary extra code?

Upvotes: 2

Views: 2118

Answers (2)

D V
D V

Reputation: 348

Singleton would be the right way to do.

The main problem with using a global variable instead of a singleton for these purposes would be that in case you have a local variable money in some other entity, the compiler would not be implicitly able to identify which money you were referring to.

So, in case you decide to add money as a variable at some other location, and you try to update this global money variable inside the same, it would end up modifying your local variable, and would not update your global one.

But, when you are using a singleton to set or get such a property, you would be safe from this situation.

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.

Or, you could just go with using something like:

struct MyGlobalItems {
    static var money: Int = 0
}

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

Upvotes: 0

Ugo Arangino
Ugo Arangino

Reputation: 2958

Actually a Singleton is a special case of a global variable. Accessing the global Singleton instance is just shadowed. This helps to keep the global namespace cleaner.

But a Singleton SHOULD NOT be used for global accesses. In iOS Singletons are used for unique resources like file system, network, user data, etc.

I suggest you to create an instance at the root of your application and inject this where you need it. This makes also testing easier and keeps your code clean. There you can also use the observer pattern to avoid the global NotificationCenter.

FYI: Communication Patterns

Upvotes: 5

Related Questions