Can Someone explain me few things regarding the Singleton implementation in Apple's documentation here.
Link: - http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html
Go to Creating a Singleton Instance in the link.
I tried but couldn't understand few things:-
What does [super allocWithZone:NULL] in + (MyGizmoClass*)sharedManager does.?
Why does allocWithZone call sharedManger method and return a retain call on its return type when retain itself returns self ?
If the Singleton has some instance variables in it, where should they be initialized ?
If anyone could briefly explain working of allocWithZone and sharedManager methods here , a lot of these questions would automatically be answered.
That implementation is generally considered over_kill. There is a lot of protections against a programmer trying to mis-use the singleton which is generally not considered necessary.
Here is an example of a more simple implementation from Yoga:
+ (id)sharedFoo
{
static dispatch_once_t once;
static MyFoo *sharedFoo;
dispatch_once(&once, ^ { sharedFoo = [[self alloc] init]; });
return sharedFoo;
}
Here goes - I have paraphrased your questions:
What does [super allocWithZone:NULL] do?
This is the same as saying [super alloc]. The withZone part is to do with where in memory your object will be stored. In practice, it would be very rare to use it. See this question for more info - what is difference between alloc and allocWithZone:?
Why does the retain method return itself (and not increment the retain counter)
Singletons are kept alive throughout the life of your application - you don't care about the retain count, because there's no situation in which you would want to deallocate your singleton. retain returns self as a courtesy and convention (and to allow nested expressions).
If the Singleton has some instance variables in it, where should they be initialized ?
Up to you. Typically you would initialise them in the init method, as per a normal object.
Related
+ (id)packetWithType:(PacketType)packetType
{
return [[[self class] alloc] initWithType:packetType];
}
- (id)initWithType:(PacketType)packetType
{
if ((self = [super init]))
{
// code
}
return self;
}
Why do we need first class method, isn't second one just enough for initialization ??
There are two reasons for having convenience constructor class methods. The first one is, that the idiom of [[Thing alloc] initWithFoo: xyz] is really common but inconvenient to have to type anywhere. So, [Thing thingWithFoo: xzy] is a common abbreviation.
A deeper reason has to do with reference counting. Methods starting with init are supposed to return a reference of the instance, ownership of which is transferred to the caller. Wheras the convenience class methods usually return autoreleased references:
+ (id)packetWithType:(PacketType)packetType
{
return [[[[self class] alloc] initWithType:packetType] autorelease];
}
This is important to know in order to avoid dangling references and/or memory leaks:
Thing* thing = [[Thing alloc] initWithFoo: xyz];
// Now, *I* own the reference and *I* am responsible for releasing
// it, when I no longer need it.
[thing release]
On the other hand, the reference returned by
Thing* thing = [Thing thingWithFoo: xyz];
is owned by the "nearest" NSAutoreleasePool. The caller is not responsible for releasing it (in fact, that would be wrong!). If the reference is to be kept around, the caller must actually retain it here:
self->myMember = [thing retain];
You should know about these conventions even when using ARC, as the underlying rules are still in effect, even if (under ARC) it's the compiler, who generates the code to obey them. The NARC acronym is a nice way to remember, which method name prefixes come with certain responsibilities. This answer has the details.
Convenience constructors have their place in the language for some reasons. Of course using them is usually shorter but there are other advantages as well:
The object is not yet allocated when they are called so the method can decide which class to allocate. Class clusters might use this to find the proper class depending on the parameters of the constructor.
The method might also decide to return an already existing object from a shared cache.
The return value can be statically typed.
Note that your convenience constructor would typically be:
+ (Packet *)packetWithType:(PacketType)packetType
{
return [[self alloc] initWithType:packetType];
}
Now the return type is statically typed and we don't send the (redundant) class message to the class object. With recent compiler versions one could use instancetype as the return type.
I’m working in a pure iOS5/ARC environment, so I can use __weak references as needed. I do reference ivars in a block in many situations, most notably, animation blocks that move views around, which are properties of say, my view controller class.
My question:
In the most trivial use of ivars in a block, am I creating a reference cycle? Do I need to use the __weak self / strong self technique everytime I write a block that manipulates instance variables of the containing object?
I’ve been re-watching the 2011 WWDC Session #322 (Objective-C Advancements in Depth) to understand the nuances regarding the 3 minute segment starting at time index 25:03 about “Reference Cycle Via Captured Self”. To me, this implies any usage of ivars in a block should be safeguarded with the weak self / strong self setup as described in that segment.
The sample method below on a view controller, is typical of animations I do.
In the openIris block, is it wrong to reference ivars “_topView” and “_bottomView” as I have?
Should I always setup a __weak reference to self before the block, then a strong reference inside the block to the weak reference just setup prior, and then access the ivars through that strong reference within my block?
From the WWDC session, I understand that referencing ivars in a block is really creating a reference to the implied self that these ivars hang off of.
To me, this implies that there really isn’t any simple or trivial case where it is correct to access ivars in a block without the weak/strong dance to ensure no cycles. Or am I reading to much into a corner case that doesn’t apply to simple cases, such as my example?
- (void)openIrisAnimated:(BOOL)animated
{
if (_isIrisOpened) {
NSLog(#"Asked to open an already open iris.");
return; // Bail
}
// Put the common work into a block.
// Note: “_topView” and “_bottomView” are the backing ivars of
// properties “topView” and “bottomView”
void (^openIris)() = ^{
_topView.frame = CGRectMake(....);
_bottomView.frame = CGRectMake(....);
};
// Now do the actual opening of the iris, whether animated or not:
if (animated) {
[UIView animateWithDuration:0.70f
animations:^{
openIris();
}];
}
else {
openIris();
}
_irisOpened = YES; // Because we have now just opened it
}
Here’s how I’d re-write the openIris block piece using the guidance from Session #322, but I’m just wondering if all my similar blocks require this weak/strong reference dance to ensure correctness and stability:
__weak MyClass *weakSelf = self;
void (^openIris)() = ^{
MyClass *strongSelf = weakSelf;
if (strongSelf) {
strongSelf.topView.frame = CGRectMake(....);
strongSelf.bottomView.frame = CGRectMake(....);
}
};
Is this in fact, necessary?
There is only a cycle here if self then goes on to hold a reference to the block (or something owned by self). If not you're good to go as the lifetime of the block is not dictated by the self it retained.
So in your particular example, you seem to be in the clear. Animation blocks don't need to participate in the weak/strong self dance.
The case to worry about is something like addObserverForName:object:queue:usingBlock:. The docs say, "The block is copied by the notification center." Under ARC, that word "copy" is a red flag; now you need to take steps so that you (the caller) will not leak.
EDIT: Also, sometimes ARC itself will alert you. The completion block of -[UIPageViewController setViewControllers:direction:animated:completion:] is a case in point. I would never have suspected that using self here might cause a retain cycle, but ARC warned that it would, so I did the weak-strong dance just in case.
I was told by a fellow StackOverflow user that I should not use the getter method when releasing a property:
#property(nonatmic, retain) Type* variable;
#synthesize variable;
// wrong
[self.variable release];
// right
[variable release];
He did not explain in detail why. They appear the same to me. My iOS book said the getter on a property will look like this:
- (id)variable {
return variable;
}
So doesn't this mean [self variable], self.variable, and variable are all the same?
For a retained property with no custom accessor, you can release the object by:
self.variable = nil;
This has the effect of setting the ivar (which may not be called 'variable' if you have only declared properties) to nil and releasing the previous value.
As others have pointed out, either directly releasing the ivar (if available) or using the method above is OK - what you must not do is call release on the variable returned from a getter.
You can optionally write custom getter behavior, which may result in completely different behavior. So, you cannot always assume that [variable release] has the same results as [self.variable release].
As well, you can write custom properties without an exclusive ivar backing them... it can get messy fast if you start releasing objects from references returned by getters!
There may be additional reasons that I'm unaware of...
A typical getter will look more like this:
- (id)variable {
return [[variable retain] autorelease];
}
So if you use [self.variable release] you have an additional retain and autorelease that you don't really need when you just want to release the object and that cause the object to be released later than necessary (when the autorelease pool is drained).
Typically, you would either use self.variable = nil which has the benefit that it also sets the variable to nil (avoiding crashes due to dangling pointers), or [variable release] which is the fastest and may be more appropriate in a dealloc method if your setter has custom logic.
not all getters take this form:
- (id)variable { return variable; }
...that is merely the most primitive form. properties alone should suggest more combinations, which alter the implementation. the primitive accessor above does not account for idioms used in conjunction with memory management, atomicity, or copy semantics. the implementation is also fragile in subclass overrides.
some really brief examples follow; things obviously become more complex in real programs where implementations become considerably more complex.
1) the getter may not return the instance variable. one of several possibilities:
- (NSObject *)a { return [[a copy] autorelease]; }
2) the setter may not retain the instance variable. one of several possibilities:
- (void)setA:(NSObject *)arg
{
...
a = [arg copy];
...
}
3) you end up with memory management implementation throughout your program, which makes it difficult to maintain. the semantics of the class (and how it handles instance variables' ref counting) should be kept to the class, and follow conventions for expected results:
- (void)stuff:(NSString *)arg
{
const bool TheRightWay = false;
if (TheRightWay) {
NSMutableString * string = [arg mutableCopy];
[string appendString:#"2"];
self.a = string;
[string release];
// - or -
NSMutableString * string = [[arg mutableCopy] autorelase];
[string appendString:#"2"];
self.a = string;
}
else {
NSMutableString * string = [arg mutableCopy];
[string appendString:#"2"];
self.a = string;
[self.a release];
}
}
failing to follow these simple rules makes your code hard to maintain and debug and painful to extend.
so the short of it is that you want to make your program easy to maintain. calling release directly on a property requires you to know a lot of context of the inner workings of the class; that's obviously bad and misses strong ideals of good OOD.
it also expects the authors/subclassers/clients to know exactly how the class deviates from convention, which is silly and time consuming when issues arise and you have to relearn all the inner details when issues arise (they will at some point).
those are some trivial examples of how calling release on the result of a property introduces problems. many real world problems are much subtler and difficult to locate.
I am implementing an object reuse scheme using a singleton class.
What I do basically is:
MyClass* obj = [[MyClassBank sharedBank] getReusableItem];
The bank is just an NSMutableSet tweaked for optimum reusability. When I was happily implementing this Singleton, I had in mind that I will just do the following when I am done with "obj":
[[MyClassBank sharedBank] doneWithItem:obj];
Currently, My code would work if I where to use it this way, but I later realized that I sometimes add "obj" to an "NSCollection", and sometimes I call:
[theCollection removeAllObjects];
At first I thought about making my own class that is composed of a collection, then I would iterate the objects within the collection and call:
[[MyClassBank sharedBank] doneWithItem:obj];
But, that's too much of a hassle, isn't?
A neat idea (I think) popped into my mind, which is to override: -(oneway void)release;, so, I immediately jumped to Apple's documentation, but got stuck with the following:
You would only implement this method to define your own reference-counting scheme. Such implementations should not invoke the inherited method; that is, they should not include a release message to super.
Ao, I was reluctant to do that idea .. basically:
-(oneway void)release{
if ([self retainCount] == 1) {
//This will increment retain count by adding self to the collection.
[[MyClassBank sharedBank] doneWithItem:self];
}
[super release];
}
Is it safe to do that?
PS: Sorry for the long post, I want the whole idea to be clear..
EDIT:
How about overriding alloc alltogther and adding [[MyClassBank sharedBank] getReusableItem]; there?
Suggested method:
You're playing with the reference counting system. 99.9999999999999999% of the time this is a bad idea. I would highly recommend going with a different mechanism. Perhaps these objects could implement their own reference count that's independent of the retainCount? Then you could use that referenceCount to actually control when an object is ready to be re-used or not.
Not suggested method:
If, for some weird reason, you can't do that, then you could do the following thing that is still a bad idea and that i don't recommend you actually use:
You can override dealloc:
- (void)dealloc {
[ivar release], ivar = nil;
[anotherIvar release], anotherIvar = nil;
somePrimitive = 0;
// do not call [super dealloc]
}
- (void)_reallyDealloc {
[self dealloc]; // clean up any ivars declared at this level
[super dealloc]; // then continue on up the chain
}
Basically, the dealloc method would be the point at which the object is ready for re-use. When you're totally done with the object and finally want it to go away, you can use the _reallyDealloc method to continue on up the chain, eventually resulting in the object getting freed.
PLEASE don't do this. With things like Automatic Reference Counting, this is going to introduce you into a world of hurt and really bizarre debugging scenarios. A lot of the tools and classes and stuff depend on the reference counting mechanism to be working without alteration, so screwing around with it is usually not a Good Idea™.
For ppl who find this approach interesting/useful, Here is a cleaner way than calling [super dealloc]; directly (which is definitely bad)
//BAD!
//-(void)dealloc{
// for some reason, the retainCount at this point == 1
// if (![[BankStep sharedBank] purgeFlag]) {
// [self resetObject];
// [[BankStep sharedBank] doneWithItem:self];
// } else {
// [children release];
// [super dealloc];
// }
//}
by calling [[Bank sharedBank] purgeBank]; , set the flag to true, then remove all objects from the NSSet.
Adapted solution:
#Joe Osborn idea of using categories to implement a returnToBank Method!
I'm from the C++ world so the notion of assigning this makes me shudder:
this = new Object; // Gah!
But in Objective-C there is a similar keyword, self, for which this is perfectly acceptable:
self = [super init]; // wait, what?
A lot of sample Objective-C code uses the above line in init routines. My questions:
1) Why does assignment to self make sense (answers like "because the language allows it" don't count)
2) What happens if I don't assign self in my init routine? Am I putting my instance in some kind of jeopardy?
3) When the following if statement fails, what does it mean and what should I do to recover from it:
- (id) init
{
self = [super init];
if (self)
{
self.my_foo = 42;
}
return self;
}
This is a topic that is frequently challenged by newcomers:
Wil Shipley: self = [stupid init];
Matt Gallagher: What does it mean when you assign [super init] to self?
Apple documentation: Implementing Initializers
Cocoa-Dev: self = [super init] debate
Basically, it stems from the idea that a superclass may have over-ridden the designated initializer to return a different object than the one returned from +alloc. If you didn't assign the return value of super's initializer into self, then you could potentially be dealing with a partially initialized object (because the object that super initialized isn't the same object that you're initializing).
On the whole, it's pretty rare for super to return something different, but it does happen in a couple of cases.
In Objective-C, initializers have the option of returning nil on failure or returning a completely different object than the one the initializer was called on (NSArray always does this, for example). If you don't capture the return value of init, the method might be executing in the context of a deallocated object.
Some people disagree about whether you should do the whole assign-to-self rigamarole if you don't expect to get something else back from the superclass initializer, but it's generally considered to be good defensive coding.
And yes, it looks weird.
It is true that init may return nil, if the initialization fails. But this is not the primary reason why you should assign to self when you implement your own initializers.
It has been mentioned before, but it is needed to stress even harder: the instance returned from an initializer may not be the same instance as the one you sent in, in fact it may not even be of the same class!
Some classes use this as a standard, for example all initializer to NSString and NSArray will always return a new instance of a different class. Initializers to UIColor will frequently return a different instance of a specialized class.
And you yourself can happely implement something like this if you want:
-(id)initWithName:(NSString*)name;
{
if ([name isEqualToString:#"Elvis"]) {
[self release];
self = [[TheKing alloc] init];
} else if (self = [super init]){
self.name = name;
}
return self;
}
This allows you to break out the implementation of some special case into a separate class, without requiring the clients of your API to care or even know about it.
All the other points here are valid, but it's important for you to understand as well that self is an implicit parameter to every Objective-C method (objc_msgSend() passes it) and can be written to, just like any other method parameter. (Writing to explicit parameters is generally frowned upon, unless they are out parameters.)
Typically, this is only done in the -init method, for the reasons others have stated. It only has any effect because self is returned from the method and used in the assignment id obj = [[NSObject alloc] init]; It also affects the implicit resolution of ivars, because, for example, if myVar is an ivar of my class, then accessing it in a method causes it to be implicitly resolved to self->myVar.
I'm still new to Objective C, but this post helped me in understanding this.
To sum it up, most init calls return the same object that self is already initialized to. If there is an error, then init will return nil. Also, some objects such as singletons or unique objects (like NSNumber 0) will return a different object than the one initialized (the singleton or a global 0 object). In these situations you need to have self reference that object. I'm by no means an expert in what is going on behind the scenes here, but it makes sense on the surface, to me.
If [super init] returns nil that means that you have been deallocated and your self parameter is now an invalid pointer. By blindly following the self = [super init] convention you will save you from potentially nasty bugs.
Consider the following non-typical initializer:
- (id)initWithParam:(id)param {
if (!param) {
// Bad param. Abort
self = [super init]; // What if [super init] returns nil?
[self release];
return nil;
}
else
{
// initialize with param.
...
}
}
Now what happens if my superclass decides to abort and return nil? I have been de-allocated and my self parameter is now invalid and [self release] will crash. By re-assigning self, I avoid that crash.