How to reset singleton instance?

All you want is possible, but highly unrecommended :) Because singletons by design should not fall back to nil.

First, if you want to change currentUser, it must be var. Then if you want it to be nil, it must by optional type and you should unwrap it when using.

static var currentUser: User? = User()

I would propose to not change currentUser or make it non-static (for example, a property of some UsersManager.

Also you can change properties of currentUser (like name, loggedIn). At last, take a look at this answer: https://stackoverflow.com/a/28398974/326017 - it describes your situation.


You can not do that if you declare currentUser as let. It should be var instead, or better still private (set) var. Also you can not assign currentUser with nil if its type is User (inferred from the way you assign it at the moment). Instead, it should be User?.

For example, something like this:

/// ...

static private (set) var currentUser: User? = User()

static func resetCurrentUser() {
    currentUser = nil
}

// ...

private (set) allows changes to the property only within the scope of current file, and for the rest of your code it will be seen as let. Then method resetCurrentUser() can be used to put it to nil.


Or even this:

// ...

private static var _currentUser: User?

static var currentUser: User {
    if _currentUser == nil { _currentUser = User() }
    return _currentUser!
}

static func resetCurrentUser() {
    _currentUser = nil
}

// ...

You can have currentUser as computed property that guarantees to return a value. So you can reset the user to nil, yes. But if later you will try to read from there again a new instance will be created automatically.

Be careful with multithreaded access, though.


I create all my Singletons with an optional Singleton instance. However I also make this private and use a function to fetch it. If the Singleton is nil it creates a new instance.

This is actually the only good way to set up a Singleton. If you have a regular object that you can't deinitialize it's a memory problem. Singletons are no different, except that you have to write a function to do it.

Singletons have to be completely self managed. This means from init to deinit.

I have a couple of templates on github for Singeltons, one of them with a fully implemented read/write lock.

class Singleton {

    private static var privateShared : Singleton?

    class func shared() -> Singleton { // change class to final to prevent override
        guard let uwShared = privateShared else {
            privateShared = Singleton()
            return privateShared!
        }
        return uwShared
    }

    class func destroy() {
        privateShared = nil
    }

    private init() {
        print("init singleton")
    }

    deinit {
        print("deinit singleton")
    }
}

Tags:

Ios

Swift