Singleton or Class Methods

After reading the answers to the question about singles in Objective-C, it seems that every decision makes some trade-offs regarding streaming in an instance accessory. i.e.

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

This is essentially single-threaded access to singleton, and if it is something that is often used in the operation, it seems something that can cause unnecessary conflicts.

What is the disadvantage of simply using a class object as a singleton instance and exposing functionality using class methods, i.e.

 @interface MySingleton : NSObject { } + (void)doSomething; @end @implementation MySingleton + (void)initialize { //do some setup if necessary } + (void)doSomething { //do something } @end 

Thus, we avoid locking check + every time we want to refer to a singleton object, and we can also eliminate the need to store it in a local or ivar method.

This approach also allows the runtime to ensure that at any given time in the system there is only one instance (class object).

EDIT

Here is more than just streams, with a traditional singlet, you usually write this code:

 MySingleton *instance = [MySingleton getSharedInstance]; NSObject *someResult = [instance getResult]; //or if (instance.someProperty) { //do something } 

However, if your singleton is an instance of the class, you essentially eliminate the need to call getSharedInstance all the time. Consider this code:

 NSObject *someResult = [MySingleton getResult]; //or if ([MySingleton someProperty]) { //do something } 

I heard that you need to store your data in local static variables of the file or in global variables (yuck). But that's really not all that differs from the traditional singleton, except that you lose the properties of Objective-C 2.0 (you should use traditional access methods instead).

Here is one key compromise for me that seems like a victory. In a traditional singlet, you end up redefining -copyWithZone, + allocWithZone, -retain, -retainCount, -release and -autorelease if you really want to fix it.

This seems like a terrible job to do every time you want to write a simple Singleton object (they prove to be very useful). So why not just replace it with this:

 @implementation MySingleton + (void)initialize { //do your setup } - (id)init { NSAssert(NO, @"You should read the documentation on singletons."); } @end 

This is much easier in terms of code, and if your consumers are really not vile, they will never create two instances.

Bring to the end My question is really this:

Is there a drawback to using the Class object as an instance of your singlet?

It seems that you can follow the same steps in terms of thread safety, memory efficiency, etc., without forgetting to redefine so many methods and accessories or substitute your code with instance checks.

+6
objective-c singleton
Nov 22 '10 at 23:02
source share
4 answers

This is my first post on stack overflow ... (so get ready for stupidity)

I think there is a hybrid solution that might be useful.

I want to set and get (global) values ​​from a singleton class without calling "getSharedInstance". I would like the code to look like this ...

 frameRate = Singleton.frameRate; Singleton.frameRate = 42; 

To achieve this, each variable that we need to store in singleton has a class method getter and setter. Then the class method goes to the instance to store data in ivar. The instance does not directly access the main program.

The getter looks like this:

 + (int) frameRate { return [[Singleton instance] ivarFrameRate]; } 

An instance (ugly) instance is hidden inside the class code.

By invoking the instance method here, the class method automatically creates an instance of the object upon first use. Once a singleton instance is created, the instance stores ivars conditionally. Here I am prefixing with "ivar" to make ivar explicit.

 @property int ivarFrameRate; 

and

 @synthesize ivarFrameRate; 

This automatically creates the usual getter (and setter) methods for accessing ivar.

(edit is a complete example)

 // Singleton.h #import <Foundation/Foundation.h> @interface Singleton : NSObject { float ivarFrameRate } @property float ivarFrameRate; - (id) init; + (Singleton *) instance; + (float) frameRate; + (void) setFrameRate:(float)fr; @end 

and

 // Singleton.m #import "Singleton.h" @implementation Singleton @synthesize ivarFrameRate; static Singleton* gInstance = NULL; + (Singleton*)instance { @synchronized(self) { if (gInstance == NULL) gInstance = [[self alloc] init]; } return(gInstance); } - (id)init { self = [super init]; return self; } + (float) frameRate { return [[Singleton instance] ivarFrameRate]; } + (void) setFrameRate:(float)fr; { [[Singleton instance] setIvarFrameRate:fr]; } 
+3
Sep 28 '11 at 16:58
source share

In iOS 4.0 or later, the best solution is to simply use dispatch_once , as in

 + (id)sharedInstance { static dispatch_once_t predicate; dispatch_once(&predicate, ^{ sharedInstance = [[MyClass alloc] init]; }); return sharedInstance; } 

You can also consider using a single dispatch_queue to serialize access to the internal elements of a class. If all your public methods just run the block in the same dispatch_queue, you don't have to worry about concurrency issues.

+5
Nov 23 '10 at 1:21
source share

This is great, but it just changes your circumstances, but does not fix your problems. If you do not have the actual data tied to your singleton, then this will work fine. Each time you access the central data, you will need to make it thread safe.

In addition, without any iVar, I don’t know how to store data (which is intended) directly in the class.

In the above example, I would encode it this way, getting the same result that you offer, and only taking a performance hit if we create / recreate a singleton:

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

Keep in mind that in any case, if you are accessing data that potentially changes in different threads, you will have to make this code thread safe anyway, either with very careful planning or using the code to make sure there are no problems, I would recommend the mix, but when in doubt, the latter, when at all possible. =)

0
Nov 23 2018-10-10T00:
source share

If you use the class as one singleton, the only way to store data is to use static file variables and global variables. If you are going to go so far that you are making a class that you do not plan to create, you can simply use the standard C functions:

 void doSomething(void); void doSomething() { //do something } 
0
Nov 23 '10 at 6:55
source share



All Articles