2

I have written a helper struct for saving and loading stuff to NSUserDefaults.

import UIKit

struct Database {

    static let defaults = NSUserDefaults.standardUserDefaults()

    static var myVariable: AnyObject?

    static func save() {
        defaults.setObject(myVariable, forKey: "myVariable")
    }

    static func load() {
        if let myVariable = defaults.objectForKey("myVariable") {
            self.myVariable = myVariable
        }
    }

    static func clear() {
        defaults.removeObjectForKey("myVariable")
    }
}

Now I can simply use Database.load() to load myVariable from NSUSerDefaults. However, the same is achievable with this code:

struct Database2 {

    static var sharedInstance = Database()

    let defaults = NSUserDefaults.standardUserDefaults()

    var myVariable: AnyObject?

    func save() {
        defaults.setObject(myVariable, forKey: "myVariable")
    }

    func load() {
        if let myVariable = defaults.objectForKey("myVariable") {
            self.myVariable = myVariable
        }
    }

    func clear() {
        defaults.removeObjectForKey("myVariable")
    }
}

Now I would use Database2.sharedInstance.load().

Which one is seen as a better practice and why? What's the use of a sharedInstance, if I can do everything I want with the static declaration?

MJQZ1347
  • 2,607
  • 7
  • 27
  • 49
  • Possible duplicate of [With the Objective-C/Swift Singleton model, why do we create a shared instance and not just use class methods?](http://stackoverflow.com/questions/24515662/with-the-objective-c-swift-singleton-model-why-do-we-create-a-shared-instance-a) –  Jan 04 '16 at 15:38

2 Answers2

1

A shared instance is recommendable, at least for the following reasons:

  1. class methods make unit testing harder
  2. you need class instances for dependency injection
  3. if later on you decide that a non-singleton is more suitable - e.g. you decide to have two persistence storages for "myVariable", then you're stuck
  4. and not lastly, class members live in the global space, and we should avoid using globals

The real question you should ask, is if you really need a singleton (with or without a shared instance) for your problem. If the only reason to have a singleton is ease-of-access, then you don't really need a singleton.

P.S. There is a very good article on objc.io about singletons, and although it was written for Objective-C, many concepts from there apply in Swift too.

Cristik
  • 30,989
  • 25
  • 91
  • 127
0
// with singleton pattern, there exist only one copy of the object
// sigleton pattern can be applied for reference type only
// let st1 = Singleton(); let st2 = Sigleton(); st1 === st2

// in your example, S is value type. All instances of S share only type properties, here only i

struct S {
    static var i: Int = 100
    var j: Int
    func foo() {
        //print(i) // error: static member 'i' cannot be used on instance of type 'S'
        print(S.i)
    }
    init(_ j: Int) {
        self.j = j
    }
}

var s1 = S(1)
var s2 = S(2)
//s1.i // error: static member 'i' cannot be used on instance of type 'S'
S.i // 100
s1.foo() // 100
s1.j // 1
s2.foo() // 100
s2.j // 2
S.i = 200
s1.foo() // 200
s2.foo() // 200

by the way, this (your) approach can be very useful and could be preferred in some situations.

user3441734
  • 16,722
  • 2
  • 40
  • 59