Objective-C - Optimizing this singleton pattern? - iphone

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.

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

How to release memory for declared object in iPhone [duplicate]

This question already has answers here:
app crash in the dealloc
(2 answers)
Closed 9 years ago.
I'm facing small problem,
I declare an array in .h file and allocate it in viewDodLoad method. In dealloc method I check if array not equal to nil then array=nil. But it's crashing in iOS 5.1.1. I can't understand reason for this crash.
My code,
#interface SampleApp : UIViewController
{
NSMutableArray *objArray;
}
#end
#implementation SampleApp
- (void)viewDidLoad
{
[super viewDidLoad];
objArray=[[NSMutableArray alloc]init];
}
-(void)dealloc
{
[super dealloc];
if (objArray!=nil)
{
[objArray removeAllObjects];
[objArray release];objArray=nil;
}
}
Add [super dealloc]; at the end of dealloc method and not at beginning. It is recommended by Apple in its documentation for dealloc method.
When not using ARC, your implementation of dealloc must invoke the superclass’s implementation as its last instruction.
Modify your code as below,
-(void)dealloc
{
if (objArray!=nil)
{
[objArray removeAllObjects];
[objArray release];objArray=nil;
}
[super dealloc];
}
Also, you need not call [objArray removeAllObjects] when you are releasing the entire array. When array is released, internally it will call release on all contained objects.
Hope that helps!
[super dealloc] method must be call in end of this method. Because you can not access variables of the superclass anymore because they are released when you call [super dealloc]. It is always safe to call the superclass in the last line.
-(void)dealloc
{
// ----------- your stuff ------------
[super dealloc];
}
With manual memory management, your -dealloc method looks as follows:
-(void)dealloc
{
[objArray release]; // objArray *may* be nil, and this is
// sufficient to release all elements as well.
// call super at the end
[super dealloc];
}
Additionally, you have a potential memory leak in your method -viewDidLoad. If you do it like your example:
- (void)viewDidLoad
{
[super viewDidLoad];
objArray=[[NSMutableArray alloc]init];
}
you may assign objArray a new pointer even if objArray already holds a valid object. The new pointer value will simply override the old, and thus you cannot release the old anymore.
One way is to check whether objArray is not nil and then release it before assigning it a new value:
- (void)viewDidLoad
{
[super viewDidLoad];
if (objArray) {
[objArray release], objArray = nil;
}
objArray = [[NSMutableArray alloc]init];
}
The better approach however is to employ "lazy initializing properties":
First, define an "internal property" for your array (unless you want the array publicly accessible). In your .m file:
// In your implementation file define a private property in a class extension:
#interface SampleApp ()
#property (nonatomic) NSMutableArray* objArray;
#end
#implementation SampleApp
#synthesize objArray = _objArray; // this will create the setter
-(void)dealloc
{
[_objArray release];
[super dealloc];
}
// Lazy init property: (this is the getter)
- (NSMutableArray*) objArray {
if (_objArray == nil) {
_objArray = [[NSMutableArray alloc] init];
}
return _objArray;
}
- (void) viewDidLoad {
[super viewDidLoad];
// When needing the array, simply *and always* access it
// through the property "self.objArray":
NSUInteger count = [self.objArray count];
}
...
Lazy initialization of properties are quite handy. Basically, you won't worry anymore if they are initialized or not - they simply are, when you use the property accessor.

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

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.

iPhone : copyWithZone : releasing an object before its return?

I read in the apple documentation about copyWithZone : "The returned object is implicitly retained by the sender, who is responsible for releasing it".
But... How may I release something I return... I'm going crazy !
Sample of code :
- (id)copyWithZone:(NSZone *)zone {
MyObject* obj = [[[self class] allocWithZone:zone] init]; // explicit retain
[obj fillTheObj];
return obj; // implicit retain
}
Where should be the told release ?
I retain twice ? Uhhh...
The sender is responsible for releasing. That means whoever calls your copy method takes ownership, i.e.:
MyObject *obj = ...
MyObject *aCopy = [obj copy];
... do stuff with aCopy
[aCopy release];