Creating a singleton class with dispatch_once for the hiearchy class

I have 2 child classes that inherit from MyClass, and each child class must be single.

I used this template to get a static instance when I don't have other classes that inherit:

+ (MyClass *)getInstance { static dispatch_once_t once; static MyClass *instance; dispatch_once(&once, ^{ instance = [[MyClass alloc] init]; }); return instance; } 

It works just fine. Now, if I add two new child classes, FirstClass and SecondClass, both of which inherit from MyClass, how can I restore the corresponding ChildClass?

 dispatch_once(&once, ^{ // No longer referencing 'MyClass' and instead the correct instance type instance = [[[self class] alloc] init]; }); FirstClass *firstClass = [FirstClass getInstance]; // should be of FirstClass type SecondClass *secondClass = [SecondClass getInstance]; // should be of SecondClass type 

Doing the above means that I always return some class that I created 1st, as my type is the second class:

 first: <FirstClass: 0x884b720> second: <FirstClass: 0x884b720> // Note that the address and type as identical for both. 

What is the best way to create matching single single classes without adding the getInstance method to each of the child classes?

+8
multithreading objective-c singleton class-hierarchy
source share
3 answers

Unless you have a good reason, you should avoid subclassing singles. This creates a very confusing situation. If you create a singleton MyClass , can you create a singleton FirstClass ? Since FirstClass can always be used anywhere in MyClass , it can be used (according to Liskov), now there are three "singleton" MyClass objects. Now ObjC is very free from singletones, and that's good, but it's still very strange.

Alright, what about your problem? This decision is first, then the answer. The solution is that MyClass probably should not be singleton, as discussed above. Get rid of getInstance in the superclass and just define it in subclasses.

The answer to what happens is in your dispatch_once . In all cases, you are passing the same static token once . dispatch_once will be executed no more than once per a given token. The only way around this is to pass different tokens for each class, and I don’t know how to do this without duplicating the dispatch_once code in each file. You can try to create different once tokens for each subclass, but most likely it will be more problems and code than just duplicating the sharedInstance method.

By the way, do not call it getInstance . "get" has special meaning in ObjC, and you don't mean it here, so it is confusing. This is usually called sharedInstance or better than sharedSomething , where "something" is your class. If you really mean that there must be MyClass and must be FirstClass and must be SecondClass , you can implement sharedInstance in all three.

+6
source share

You know that singleton are harsh, right? many singletones are a big problem. end of caution.


you can just use dispatch_once to create a basic singleton. then your database may contain a map (for example, the dictionary {key: ClassName | value: Instance}) of its derived types.

which you use dispatch_once suggests that this will be used in a multi-threaded context. In this case, you will need to protect the interaction with the dictionary using the mutex.

then your messages from subclasses will be determined based on the message class ( self ) that the class is looking for (creating this instance, if necessary).

+1
source share

use id in your myClass in firstClass like this

 +(instancetype)sharedInstance { static id sharedInstance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [[[self class] alloc] init]; }); return sharedInstance; } 

I think this should work

0
source share

All Articles