Is self release, released actual object? - iphone

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();
}

Related

Overriding alloc init for singleton class [duplicate]

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 :-)

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

how to make static variable initialized

I want to save the "dataFilePath" as a static variable so that it can be initialized when first time use "Constants" and no need to instantiate the Class , for example [Constants SDataFilePath]. But the trues is that the init method is not called. How can I do to meet my request? (In Java the construct method will be called the fist time to access the Class).
#implementation Constants
static NSString *dataFilePath;
-(id)init
{
NSLog(#"init!");
if(self = [super init]) {
dataFilePath = [self getDataFilePathWithArg:dbfile];
}
return self;
}
+(NSString *)SDataFilePath {
return dataFilePath;
}
....
#end
Well you could make Constants a singleton. Leave your code how it is and add this method to the .m:
+ (Constants *)sharedConstants
{
static Constants *_sharedConstants = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedConstants = [[self alloc] init];
});
return _sharedConstants;
}
And the method declaration to the .h:
+ (Constants *)sharedConstants;
Then access your variable like this:
[[Constants sharedConstants] SDataFilePath]
That will force an init the first time you access [Constants sharedConstants] (and only the first time). Also, you'll need to change +(NSString *)SDataFilePath to an instance method, not class method:
-(NSString *)SDataFilePath
This cannot be done this way. Any reason why you want this path to be static? You might want to look into setting dataFilePath with a getter, but no setter and instantiating the class as a singleton. That way you can set the path by some internal method and share the instance as a singleton. See here

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.

method name part of same singleton class?

I have a class, in that class I have set up a singleton patter and have a method, here is a short example of what it looks like.
#pragma mark Singleton Methods
+ (id)sharedManager {
#synchronized(self) {
if (sharedMyManager == nil)
sharedMyManager = [[self alloc] init];
}
return sharedMyManager;
}
- (id)init {
if (self = [super init]) {
//so some init stuff here
//...
}
-(void)savemethod {
//etc etc
}
I'm wondering if I am to call/initalize the singleton class to be used like so
//set up plist controller class as a singleton so that you dont loose cache numbers etc
EnginePropertiesController *enginePC = [EnginePropertiesController sharedManager];
then later on in the same class where I have initialized the singleton I call the save method...
[enginePC saveMethod];
So what im wondering is saveMethod part of the same instance? I think it is because i am using the same initialization name enginePC.. but would like some clarification on this.
If I'm understanding you, you are correct that saveMethod would be called on the singleton instance. What you name a pointer has no bearing on what it points to.