Overriding alloc init for singleton class [duplicate] - iphone

This question already has answers here:
How to properly implement ARC compatible and `alloc init` safe Singleton class? [duplicate]
(3 answers)
Closed 8 years ago.
I am writing some singleton class in my framework and I do not want other developer to call init and alloc on those singleton classes so I have override those methods but since I am using ARC, so my code for singleton class is:
+(MFSingletonClass*) sharedInstance
{
static dispatch_once_t pred = 0;
dispatch_once(&pred, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
and following are alloc and init methods:
+ (id)alloc {
static dispatch_once_t pred = 0;
dispatch_once(&pred, ^{
sharedInstance = [super alloc];
});
return sharedInstance;
}
- (id)init {
__weak typeof(self) weakSelf = self;
static dispatch_once_t pred = 0;
dispatch_once(&pred, ^{
static BOOL init = NO;
if (!init) {
init = YES;
typeof(self) strongSelf = weakSelf;
strongSelf = [super init];
}
});
return weakSelf;
}
I wanted to know whether my implementation of alloc and init method is proper or not?
Thanks in advance!

You ask whether your "implementation of alloc and init method is proper or not?"
Depends on how you define "proper"...
Your code is not incorrect as far as it goes, in that it usually does work, but the init is, let's say, over-cautious and a little incorrect, and there is a trick or two you missed.
Looking at the init you double up checking whether the initialisation has been run:
dispatch_once; and
a BOOL flag init.
The block passed to dispatch_once will be executed at most once, and at that time init will be NO. Overkill. Removing that you get:
- (id)init
{
__weak typeof(self) weakSelf = self;
static dispatch_once_t pred = 0;
dispatch_once(&pred,
^{
typeof(self) strongSelf = weakSelf;
strongSelf = [super init];
});
return weakSelf;
}
Now consider [super init], this is a method call on the current instance, that is though it is not explicit this expression references self. Given that your efforts to avoid a retain cycle are wasted. Furthermore in those efforts you assigned the result of [super init] to a block-local variable strongSelf while init returns weakSelf - this is the reason for the "usually does work" remark above, most calls to [super init] do actually return the same object, but the need not. If we remove the use of weak references we solve both these issues at once:
- (id)init
{
static dispatch_once_t pred = 0;
dispatch_once(&pred,
^{
self = [super init];
});
return self;
}
Bot doesn't this leave us with a retain cycle? No, the object referenced by self does not keep a reference to the block, so the block having a reference back to the object doesn't matter.
The "as far as it goes" remark above
The default alloc method just calls allocWithZone:, the latter takes a memory zone - something which is no longer used but exists for historical reasons. Therefore you should really implement allocWithZone: rather than alloc to catch all allocations - the code would follow the same algorithm as your alloc.
Then there is the copy and copyWithZone: pair. If you want a singleton you don't copies of it, so you should implement copyWithZone: (which copy just calls as will alloc/allocWithZone:) and return self:
- (id) copyWithZone:(NSZone *)zone
{
return self;
}
The missed trick
So your code works as far as it goes, apart from the case where [super init] returns a different object, but was overcomplicated; clean up init to address that.
However if you dig up Apple's now deprecated Cocoa Objects documentation you'll find Apple's old recommendation for producing a true singleton. Under ARC you can ignore the MRC overrides, and you can add the use of GCD as you have done to ensure concurrent correctness, and that will leave you with one trick: Apple implement allocWithZone: by calling sharedManager (your sharedInstance) and having that in turn call allocWithZone on super. With your code that would be:
+ (MFSingletonClass*) sharedInstance
{
static MFSingletonClass *sharedInstance = nil;
static dispatch_once_t pred = 0;
dispatch_once(&pred,
^{
sharedInstance = [[super allocWithZone:NULL] init];
});
return sharedInstance;
}
+ (id)allocWithZone:(NSZone *)ignore
{
return [self sharedInstance];
}
Which is a little cleaner, but your approach works fine as well.
And kudos for knowing the difference between a true singleton and just a shared instance!
HTH

With singletons, you have two choices: Write the very simple sharedInstance method and be done with it, or try to do all kinds of ingenious tricks to keep people from instantiating more objects. Trying to instantiate the singleton through any call other than sharedInstance is a programming error. You don't write complicated code to prevent programming errors. And you'll never get it right anyway :-)

Related

Objective C Singleton Class [duplicate]

This question already has answers here:
Using a singleton to create an array accessible by multiple views
(2 answers)
Closed 9 years ago.
I have created a singleton class in Objective C. Like the one below:
#interface SingletonClass : NSObject{
NSMutableArray *instanceArray;
}
#property(nonatomic,retain)NSMutableArray *instanceArray;
+(SingletonClass*)sharedInstance;
#end
#implementation SingletonClass
#synthesize instanceArray;
static SingletonClass *sharedInstance =nil;
+(SingletonClass*)sharedInstance
{
if(sharedInstance==nil){
sharedInstance=[[super allocWithZone:NULL]init];
}
return sharedInstance;
}
-(id)init{
self=[super init];
if(self){
instanceArray=[[NSMutableArray alloc]init];
[instanceArray addObject:#"One"];
[instanceArray addObject:#"Two"];
}
return self;
}
+(id)allocWithZone:(NSZone *)zone{
return [self sharedInstance];
}
#end
I know it can be accessed from anywhere with the following piece of code:
SingletonClass *singletonObject=[SingletonClass sharedInstance];
And the instanceArray can be accessed anywhere by singletonObject.instanceArray.
Now my question is, is is possible to modify the array by adding new objects to it ? Will that be persisted ? Because i tried to add an object from one class
[singletonObject.instanceArray addObject:#"Three"];
When i checked the array contents from another class, the array consisted of only two values which are initialized by default. The value which i added from another class didnt show up.
What could be the problem ? Am I missing something here ? Please help.
Drop the allocWithZone: implementation entirely. It is prone to error and a distinctly odd thing to do. The reality is that if you have code that is using your singleton class and not going through sharedInstance then that code is broken. Attempting to hide that brokenness is just going to cause pain later.
Just do this one:
+(instancetype)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[SingletonClass alloc] init];
});
return sharedInstance;
}
If you aren't seeing updates to the array in your other class, then there is some other bug.
Your implementation of allocWithZone: is never called because you are calling the [super allocWithZone:], also i don't think you need this method.
i would change your class method with this:
+(instancetype)sharedInstance
{
if(sharedInstance==nil){
sharedInstance = [[SingletonClass alloc]init];
}
return sharedInstance;
}
and if you want to be more secure that you are not going to create another instance of your object use dispatch_once:
+(instancetype)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[SingletonClass alloc] init];
}
return sharedInstance;
}
I think that you forgot the ! before self in init method :
-(id)init {
self = [super init];
if(!self) {
instanceArray=[[NSMutableArray alloc]init];
[instanceArray addObject:#"One"];
[instanceArray addObject:#"Two"];
}
return self;
}
That's why each time you get a new instance of your singleton

Is self release, released actual object?

I have a singleton class which is allocation object only one time in whole project. Few code line is below..
declaration...
....
MyClassName *classObject = nil
In the init method, the code is like below..
-(id) init(){
self = [super init];
if(classObject == nil){
1. Allocate object code here
2. classObject = self;
3. return classObject
} else {
return classObject;
}
}
But my problem is that how will I dealloc this object. I am calling this init method from all the class and it is returning classObject reference every time.
My approach....
From the dealloc method in appdelegate.m, I am calling a function (releaseObject)which is defined in MyClassName . Here is the definition of function body...
-(void) releaseObject {
[self release]; // Confusion: Will it dealloc classObject reference?
[super release];
}
Is this good idea dealloc this object? My problem is that I don't have to dealloc object until application is not being closed.
The answer is don't bother ever to release the singleton. It is supposed to last the lifetime of the application anyway and will go away automatically along with everything else when the process terminates. You may find that the dealloc method on your app delegate never gets called for the same reason.
If you have clean up to do on application close, it's probably better to move that into a separate method and just call that when the application is about to terminate.
a simpler pattern for a singleton IMO is to have a class method to return the singleton instance and not mess about with releasing stuff in init.
+(MyClass*) sharedInstance
{
static MyClass* theInstance = nil;
static dispatch_once_t pred;
dispatch_once(&pred, ^{ theInstance = [[MyClass alloc] init]});
return theInstance;
}
The above uses dispatch_once to ensure the initialising block only happens once in the lifetime of the application. You can still create other instances by calling init directly but that is advantageous IMO.
I'd recommend to make an extra class method in your singleton:
static MyClassName *classObject = nil;
...
+ (MyClassName *)sharedInstance {
...
}
+ (void)releaseSharedInstance {
[classObject release];
classObject = nil;
}
If your class is a singleton, in AppDelegete dealloc just call
[[YourClass instance] release];
Here is workaround via Objective C++:
class StaticOwner {
private:
id<NSObject> object;
public:
StaticOwner(id<NSObject> obj) { object = [obj retain]; }
~StaticOwner() { [object release]; }
id<NSObject> instance() {return object;}
};
Usage example:
+ (MySingleton*) sharedInstance {
static StaticOwner owner = StaticOwner([[[MySingleton alloc] init] autorelease]);
return owner.instance();
}

Objective-C - Optimizing this singleton pattern?

I've found that singleton pattern on the net. It seems to me it has many things that can be optimized.
-In sharedMySingleton method, no need to call a retain ? I'm not sure...
-If not, why is there a retain in allocWithZone ?
-what is the use of #synchronized. The NSAssert make think that the block can be called many times, so if yes, there should be some more code to release previous memory, or exit the block clearly without just NSAsserting, and if no, why is there this NSAssert ?
-the chain beetween sharedMySingleton and alloc seems strange. I'd wrote myself something like :
+(MySingleton*)sharedMySingleton
{
#synchronized([MySingleton class])
{
if (_sharedMySingleton == nil) _sharedMySingleton = [[self alloc] init];
return _sharedMySingleton;
}
return nil;
}
+(id)alloc
{
#synchronized([MySingleton class])
{
return [super alloc];
}
return nil;
}
Singleton pattern
#import "MySingleton.h"
#implementation MySingleton
// ##########################################################################################################
// ######################################## SINGLETON PART ##################################################
// ##########################################################################################################
static MySingleton* _sharedMySingleton = nil;
// =================================================================================================
+(MySingleton*)sharedMySingleton
// =================================================================================================
{
#synchronized([MySingleton class])
{
if (_sharedMySingleton == nil) [[self alloc] init];
return _sharedMySingleton;
}
return nil;
}
// =================================================================================================
+(id)alloc
// =================================================================================================
{
#synchronized([MySingleton class])
{
NSAssert(_sharedMySingleton == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedMySingleton = [super alloc];
return _sharedMySingleton;
}
return nil;
}
+ (id)allocWithZone:(NSZone *)zone { return [[self sharedMySingleton] retain]; }
- (id)copyWithZone:(NSZone *)zone { return self; }
- (id)retain { return self; }
- (NSUInteger)retainCount { return NSUIntegerMax; /* denotes an object that cannot be released */}
- (oneway void)release { /* do nothing */ }
- (id)autorelease { return self; }
// ##########################################################################################################
// ##########################################################################################################
// ##########################################################################################################
// =================================================================================================
-(id)init
// =================================================================================================
{
if (!(self = [super init])) return nil;
return self;
}
// =================================================================================================
-(void) dealloc
// =================================================================================================
{
[super dealloc];
}
// =================================================================================================
-(void)test
// =================================================================================================
{
NSLog(#"Hello World!");
}
#end
You shouldn't use this pattern at all (it's for a very special case of Singleton that you almost never need, and even in that case you generally shouldn't use it).
There are many good patterns discussed at What should my Objective-C singleton look like?, but most of them are outdated since the release of GCD. In modern versions of Mac and iOS, you should use the following pattern, given by Colin Barrett in the linked question:
+ (MyFoo *)sharedFoo
{
static dispatch_once_t once;
static MyFoo *sharedFoo;
dispatch_once(&once, ^{ sharedFoo = [[self alloc] init]; });
return sharedFoo;
}
I only copy it here rather than marking the question duplicate because the old question's highest-rated answers are out-dated.
No need to call retain because there is an alloc. Call retain on top of that would cause a memory leak.
There is retain on allocWithZone because it's a singleton, so we don't want to create two different instances of the class. Rather allocating a new instance we augment the retain count of the singleton instance. Why is that? Probably to prevent somebody not aware of the singleton type of the class. If he calls allocWithZone and then release the instance, everything still work fine, and he actually accessed the shared singleton instance.
#synchronized is used to prevent two calls from two different threads to enter in the if statement at the same time. So the code is thread-safe.
The NSSAssert is probably to make the app 'crash' if two instances of the singleton are ever created. It's 'just-to-be-sure' code, also called defensive programming.
Concerning the chain beetween sharedMySingleton and alloc, I think it's just fine.
In sharedMySingleton method, no need to call a retain?
alloc returns a new instance with a reference count of one, so no retain is necessary.
If not, why is there a retain in allocWithZone?
According the rules, when you call allocWithZone, you own the reference, therefore allocWithZone much increase the reference count for you. But this implementation of allocWithZone is returning the singleton instance that was already created and owned by someone else (the sharedMySingleton method). So the sharedMySingleton method creates the object with alloc, therefore it becomes an owner. And then you get the same instance through allocWithZone, therefore you become a second owner of the same instance. So the retain count must go up since there are two owners now. That is why allocWithZone needs to retain.
What is the use of #synchronized?
#synchronized allows code to be called simultaneously by multiple threads. If you will never call sharedMySingleton from more than one thread, then it is not necessary and you may omit it.
The NSAssert make think that the block can be called many times, so if
yes, there should be some more code to release previous memory, or
exit the block clearly without just NSAsserting, and if no, why is
there this NSAssert?
Because the class is intended to be a singleton, alloc should only be called once. The NSAssert() terminates the program if alloc is called more than once. Since NSAssert() terminates the program, when alloc is called a second time, no memory management is necessary.

Memory Management in Objective-C

I wanna ask if I allocated an instance variable for private use in that class, should i release it immediately on site, or i can depend on dealloc function. (because maybe i will need it on other function) ?
//Player.h
#interface Player : NSObject
{
NSMutableArray * objectArray;
}
- (void)awake;
- (void)add;
#end
//Player.m
#implementation Player : NSObject
{
-(id) init {
self = [super init];
if (self != nil ){
[self awake];
[self add];
}
return self;
}
- (void) awake {
objectArray = [[NSMutableArray alloc] init]; //is it cause leakage?
[objectArray addObject:#"foobar"];
}
- (void) add {
[objectArray addObject:#"foobar2"];
}
- (void) dealloc {
[objectArray release];
[super dealloc];
}
}
#end
or should i using property to set the objectArray iVar?
//Player.h
#interface Player : NSObject
{
NSMutableArray * objectArray;
}
#property (nonatomic,retain)NSMutableArray* objectArray;
- (void)awake;
- (void)add;
#end
//Player.m
#implementation Player : NSObject
{
-(id) init {
self = [super init];
if (self != nil ){
[self awake];
[self add];
}
return self;
}
- (void) awake {
self.objectArray = [[NSMutableArray alloc] init autorelease]; //cause leakage?
[objectArray addObject:#"foobar"];
}
- (void) add {
[objectArray addObject:#"foobar2"];
}
- (void) dealloc {
[objectArray release];
[super dealloc];
}
}
#end
if both of them doesn't cause a leakage, what type should i use?
should i always set iVar property, and access iVar value with self even if i only want to use it in this class?
I like to take the stance that if the instance variable should not be visible outside of the class then it should not be implemented as a property. But it's a personal thing that other developers may not agree with.
Either way you would need to release the objectArray in your classes dealloc method - which is what you're currently doing.
However you need to be careful with your awake method - if it's invoked multiple times then objectArray is leaked. This is the downside of not using properties. A use of self.objectArray = [[NSMutableArray alloc] init] here would have released the previous object.
In my opinion, you should only declare properties in your header if other objects are allowed to use them. There is no good reason why you would provide an -add: method (as in your example) that adds something to your array while also providing a getter for your array so other objects can manipulate it directly. It's called encapsulation.
If you do want to have the benefits of generated getters/setters for your implementation file, you can always use a class continuation (a nameless category) inside your implementation file and include your property declarations there. That way you get real, auto-generated properties that are only visible to your class' implementation.
Personally, I wouldn't use any getter or setter methods in your example. Just allocate the NSArray in your -init and release it in -dealloc. If this -awake method of yours might be called multiple times, just add an [objectArray removeAllObjects] call and you're sure to have an empty array without worrying about memory management.
It is very likely that memory will leak in your first example because you are not sending release to the previously set instance variable (if it already existed).
This is why you should use property setters - they handle all of this stuff for you.
Also, since you are obtaining ownership of the instance variable through the property (which is defined with the retain keyword), you will definitely leak memory if you don't send the instance variable the -release message in your -dealloc method.
So the verdict is that you should use the second example, not the first.

Singleton class in objective c

I have create a SinglestonClass in my code but i have a problem.
My variable are initialized in the -init method but when i call the singlestonClass these variable are re-initialize.
Can you help me for create a single initialization for my variable?
thanks.
#implementation SingletonController
#synthesize arrayPosition;
#synthesize arrayMovement;
#synthesize actualPosition;
#synthesize actualMove;
#synthesize stopThread;
+(SingletonController*)sharedSingletonController{
static SingletonController *sharedSingletonController;
#synchronized(self) {
if(!sharedSingletonController){
sharedSingletonController = [[SingletonController alloc]init];
}
}
return sharedSingletonController;
}
//I don't want a re-initialization for these variables
-(id)init{
self = [super init];
if (self != nil) {
arrayPosition = [[NSMutableArray alloc]init];
arrayMovement = [[NSMutableArray alloc]init];
actualPosition = [[Position alloc]init];
actualMove = [[Movement alloc]init];
stopThread = FALSE;
}
return self;
}
-(void) dealloc {
[super dealloc];
}
#end
Your init method should not be called by anyone except for your singleton class itself. That's what the sharedSingletonController method is for. This is your factory method that is responsible for returning the same static instance of your class. I'd also suggest that you rename the static instance of your singleton object and/or the sharedSingletonController selector itself to disambiguate between the two and for cleaner design. In this particular case, it may confuse someone who has to read your code.
Without seeing how the client code is calling on your singleton factory method, it's difficult to decipher where your problem is. We'd need to see the rest of the code including how it's being called. In your client code, you should be using something such as:
SingletonController *sigController = [SingletonController sharedSingletonController];
DO NOT DO:
SingletonController *sigController = [[SingletonController alloc] init];
Read here for more information in the Cocoa Fundamentals Guide.