Swift - How to Set a Singleton to Nil

Swift - How to set a singleton to nil

This should work:

private var _SingletonSharedInstance:MyClass! = MyClass()

class MyClass {
let prop = "test"

class var sharedInstance : MyClass {
return _SingletonSharedInstance
}

init () {}

func destroy() {
_SingletonSharedInstance = nil
}
}

But then the references to the object are still kept, so you need to do some additional things to invalidate method calls in the class.

Possible to set singleton back to nil?

Your assumption about the local reference is correct, it won't affect your singleton.

To be able to reinitialize the singleton you need to move the static variable out of your method, so it's accessible by the whole class.

static MySingleton *sharedInstance = nil;
// Get the shared instance and create it if necessary.
+ (MySingleton *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[MySingleton alloc] init];
}
return sharedInstance;
}

+ (void)resetSharedInstance {
sharedInstance = nil;
}

Note that you cannot use dispatch_once anymore, since your singleton needs obviously to be created multiple times. If you only ever call this singleton from your UI (and therefore only from the main thread), then the sample above is fine.

If you need access from multiple threads you need to put a lock around the +sharedInstance and +resetSharedInstance method, e.g.

+ (id)sharedInstance {
@synchronized(self) {
if (sharedInstance == nil) {
sharedInstance = [[MySingleton alloc] init];
}
return sharedInstance;
}
}

+ (void)resetSharedInstance {
@synchronized(self) {
sharedInstance = nil;
}
}

This is quite a bit slower than the dispatch_once variant, but in practice it won't matter usually.

How to reset singleton instance?

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")
}
}

Swift: Unwrap optional to the instance variable properly

You can write the init? of B as follows:

init?() {
guard let a = A.shared else { return nil }

self.a = a
print(a.b)
}

It's best to avoid code in the pattern:

if someVar != nil {
x = someVar!
}

guard let or if let exist to avoid such constructs.

But there is no way to avoid dealing with your optional singleton other than not making it optional. It's unusual to have an optional singleton instance.

Swift singleton that does not look like a singleton

In Objective-C an initialiser is just like any other method that is called on an instance

 [[alloc SomeClass] init]

You first alloc an instance and then explicitly invoke its initialiser.

init is able to return any object; returning self is just a convention that can be ignored in special cases, such as the one you have shown.

In Swift, init is special. An initialiser is invoked implicitly as part of the allocation

let x = SomeClass()

A Swift init implicitly returns self (or it can return nil in the case of failable initialiser that has failed). As a result, you cannot implement a "hidden singleton" in Swift by returning some other object.



Related Topics



Leave a reply



Submit