is it good form to release self in an init method when that method allocates and returns something else? - objective-c

In my code, I have something that looks like this:
#implementation MyClass
- (id) initWithType:(NSInteger)type {
[self release];
if (type == 0) {
self = [[MyClassSubclass1 alloc] init];
} else {
self = [[MyClassSubclass2 alloc] init];
}
return self;
}
//...
#end
which I think handles any potential memory leaks. However, I have seen code out there that does something similar, except it doesn't release self before reassigning it to another newly allocated instance. Is it not necessary to release self here or is the other code I've seen incorrect?

Your code looks technically correct, from a memory management perspective. Replacing self with a different alloc'd object loses the pointer to the original object, and nobody else will be able to release it, which would cause a leak. Try commenting out the release call and run it with Leaks in Instruments.
Just be cautious about opening this particular can of worms — Foundation.framework (part of Cocoa) uses class clusters for collections and strings, but doing so is a fairly advanced concept. A better approach might be to have a class method for each subclass, using the AbstractFactory pattern.
In any case, determining the subclass type based on an integer is a bad idea — any change in mapping from type to class will break dependent code. If you're going that way, why not just pass in the class object itself?

This looks like poor use of object-oriented design.
If you're creating a different instance depending on a type variable, then why don't you have subclasses for those types?
It would be much cleaner to define a base class with all the common functionality, and a subclass for each "type" variation.
What does the class do? We might be able to point you in the right direction.
Code-wise, your example code is correct, but it's generally bad practice to replace the instance with a different instance. Unless the init method is a factory method re-using instances or a singleton initializer, avoid releasing self en-lieu of another instance.

Related

Fully deallocating an Objective-C singleton

I'm new to writing singletons and I have to use one for a current iOS project. One of the requirements is that it can be killed. I know this goes against the design of a singleton, but is this something that should/could be done?
Of course it could be done, but if you're looking for an object that can be created, and then released when not needed... that sounds like a regular object. :)
Generally singletons control their own lifecycles. You're going to get one-sided discussion here unless you say more about the two requirements (one, that you use a singleton, and two, that it can be released at will), and why they both make sense in your case.
It might be because the singleton wraps some other resource that is inherently unique (like a file resource or network connection). If this is true, then generally the singleton is the "manager" of that resource, and you'd expose control of that resource via the singleton's interface.
Or it might be because the singleton object holds on to a ton of memory (a buffer of some sort), and you want to be sure that's flushed as necessary. If this is the case, then you can be smarter about each of its methods creating and releasing memory as necessary, or you can have the singleton listen for the low memory system notifications and behave appropriately.
Essentially, I'd be hard pressed to construct a case where it really made sense for the singleton object itself to be released. A single basic object takes only a handful of bytes in memory, and hurts no one by hanging around.
I know this goes against the design of a singleton
It also goes against the usual memory management patten in Objective-C. Normally, an object gets to retain another object to prevent it from being destroyed, and to release it to allow the object to be destroyed. Explicitly destroying an object, though, isn't something that other objects get to do.
Consider what would happen if object A gets the shared instance S1 of a singleton class S. If A retains S1, S1 will continue to exist even if some class method releases S and sets the global variable that points to the shared instance to nil. When the class later creates a new shared instance, S2, there will be two instances of S, namely S1 and S2. This violates the property that defines the singleton in the first place.
You might be able to get around this problem by overriding -retain and maybe swizzling -release, but that seems like a lot of complexity to solve a problem that shouldn't exist in the first place.
A possible alternative is to reset your shared object instead of trying to destroy it. You could set all it's attributes to some known (possibly invalid) state if you want, and then have a class method the re-initializes the shared object. Just be aware of the effect of all that on any objects that might be using the shared object.
Just about every singleton I've ever written (save for totally UI centric controllers) end up being refactored into not being singletons. Every. Single. One.
Thus, I've stopped writing singletons. I write classes that maintain state in instances, as any normal class should, and do so in isolation from other instances. If they are notification heavy, they always pass self as the notifying object. They have delegates. They maintain internal state. They avoid globals outside of truly global state.
And, often, there may be exactly one instance of said class in my app(s). That one instance acts like a singleton and, in fact, I might even create a convenient way of getting a hold of it, likely through the App's delegate or through a class method (that might even be named sharedInstance sometimes).
Said class includes tear-down code that is typically divided in two pieces; code to persist current state for restoration later and code that releases instance associated resources.
Convenient like a singleton. Ready to be multiply instantiated when needed.
Sure no problem. You provide a new class method: [MyClass killSingleton]; That method releases the singleton and sets its internal reference to nil. The next time someone asks [MyClass sharedSingleton], you go through the same steps you did before to create it.
EDIT: actually, in the old days such a routine could have overridden the release selector, and refused to go away. So as the first comment below states, this is an object with static scope - its kept alive through a static variable keeping a retain count of 1 on the object. However, by adding in a new class method to nil out that ivar (under ARC), thereby releasing it, achieves the desired result. Control over instantiating and releasing the static object is completely done via class methods, so is easy to maintain and debug.
It's against the concept of Singleton, but it can be implemented the following way for an ARC based project
//ARC
#interface Singleton : NSObject
+ (Singleton *)sharedInstance;
+ (void)selfDestruct;
#end
#implementation Singleton
static Singleton *sharedInstance = nil;
+ (Singleton *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[Singleton alloc] init];
}
return sharedInstance;
}
+ (void) selfDestruct {
sharedInstance = nil;
}
#end
//This can be implemented using bool variable. If bool no create new instance.
#interface Singleton : NSObject
+ (Singleton *)sharedInstance;
#end
#implementation Singleton
static Singleton *sharedInstance = nil;
+ (Singleton *)sharedInstance {
if (!keepInstance) {
sharedInstance = [[Singleton alloc] init];
keepInstance = YES;
}
return sharedInstance;
}
#end
I needed to clear out the singleton so I ended up doing the following:
- (void)deleteSingleton{
#synchronized(self) {
if (sharedConfigSingletone != nil) {
sharedConfigSingletone = nil;
}
}
}
Hope it helps.

Is it an acceptable pattern for an init method to return an object of a different type?

I'm working on bugfixes for some existing objective-c code and came across something I thought strange:
#interface ClassA : UIView
...
static ClassA* oldSelf = nil;
#implementation
- (id)initWithFrame:(CGRect)frame {
oldSelf = self;
self = [[ClassB alloc] initWithFrame:(CGRect)frame]; // xcode warns: Incompatible pointer types assigning to "ClassA *" from "ClassB *"
// ^^^^^^ Is this ok?
[oldSelf release];
return self;
}
#interface ClassB : UIView
...
#implementation
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
return self;
}
This whole thing is wrapped up into a static library. The public gets the lib.a file and ClassA.h
In code using the library, This occurs:
#import "ClassA.h"
...
// useage
ClassA *myA = [[ClassA alloc] initiWithFrame:CGRectMake(0,0,100,100)];
...
So we got an initializer for ClassA that actually returns an unrelated class. ClassA and ClassB respond to the same messages so it compiles and runs. Seems like ClassA is being used to obscure some features exposed in ClassB?
I'm curious if this is acceptable behavior, and if it's a known pattern, what is it called? Are there any side effects to this setup?
=========================================================
Thanks for everyone's answers! I think I've got it... in short, not a normal pattern, and not exactly a good idea
Kind of like a "class cluster"(abstract factory), but not quite, because a common abstract class should be returned. And since the code doesn't seem to ever intend to return anything but a ClassB object, probably not what the original author was thinking.
More like a proxy, but implemented wrong. ClassA should hold a private instance of ClassB and pass messages between the two.
=========================================================
Edited: added "oldSelf" parts...
Edited: added static library details...
Edited: added a blurb about the accepted answer...
The major disadvantage I see here is: a user of ClassA would expect that an object he just created via [[ClassA alloc] initWithFrame:...] returns YES for [object isKindOfClass:[ClassA class].
This might also lead to errors when using things like NSInvocation, because the wrong class would be used to determine the method signature, though I am not sure about that.
Due to Objective-Cs dynamic nature, this will, as you described, work, but may be confusing to use and i would strongly discourage anyone from using this pattern.
As pilavdzice said, the "right" alternative to this would be to have both ClassAand ClassB inherit from another class (an abstact superclass) which then in its initializer decides what concrete subclass to use. Good examples of this pattern, called class clusters, are NSString, NSArray and NSDictionary which all return objects of various subclasses based on how you initialize them, which is also the reason you can not subclass those directly without some effort.
It's not an unreasonable thing to do in all cases, but it's hard to say whether it's a good idea in the situation you describe. Two examples where it might be fine:
The initializer returns an instance of a more specialized subclass. For example, you might choose different implementations of a data structure depending on the number of items being stored.
The initializer returns some sort of proxy object.
Your code does seem a bit odd. At the very least, I'd expect to see a cast as a signal (both to the compiler and to future programmers) that the author knew what he was doing. A comment explaining the reason for returning a different type of object wouldn't hurt, either. Ideally, ClassB should be a subclass of ClassA since it's expected to provide the same interface.
Class clusters are implemented in this way, sort-of. A related technique, isa-swizzling can be used to implement a sort of state machine. It does require the same ivar layout to work. In terms of side effects, I believe that it may break KVO; but someone may correct me on that point.
It's certainly not common in user code to return an unrelated class, however it is common in some of Apple's frameworks to return a more specific version of a class with the same public interface.
Apple's Cocoa Fundamentals discusses in some amount of detail the fact that objects such as NSArray and NSNumber may return a different object than the class you are asking for.
That isn't a pattern I know of.
If I am understanding this correctly, the normal way to do this would be to have both classes inherit from the same abstract base class.
As #alan duncun notes, this technique is called a class cluster and is somewhat common. But your implementation is slightly incorrect. You should never return a incompatible type. In your example, ClassB should inherit from ClassA.
Well this is somewhat how NSScanner is implemented.
This way the inner class is not exposed and can not be misused. ClassB can not be initialized somewhere else other than in the implementation file of ClassA.
This makes sense if you have multiple inner classes and your initializer somehow decides which class is actually needed.
I don't see any advantages if you only use one inner class.

can we override alloc and dealloc in objective C?

I know that this is rarely required to override the alloc or dealloc methods,but if required is it possible in iPhone programming?
You can and indeed, you should (if using manual memory management) override dealloc to release any resources you hold (not forgetting to call [super dealloc] when finished). Overriding alloc is possible but, as you say, rarely needed.
In general, overriding alloc is only done when you wish to, eg, allocate an object from a pool of available instances, or perhaps allocate a variable amount of storage for the object based on some external parameter. (In C++ you can access the new parameters and allocate based on them, but Objective-C does not give you access to the initXXX parameters.)
I've never attempted any of this, and I suspect that its a bit of a minefield -- you need to study up on the structures and be pretty careful.
As Adam said, you should ALWAYS (in a reference counted environment) override dealloc if there are any retained objects held by your object.
Update: An interesting thing you can do ... in RedClass or a superclass of it code something like:
+(id)alloc {
if (self == [RedClass class]) {
return [BlueClass alloc];
}
else {
return [super alloc];
}
}
The net result is that whenever you execute [RedClass alloc] a BlueCLass object will be returned. (NB: Presumably BlueClass is a subclass of RedClass, or things will get seriously mucked up shortly after the object is returned.)
Not saying that it's a good idea to do this, but it's possible (and I don't offhand know of any cases where it wouldn't work reliably for vanilla user-defined classes). And it does have a few possible uses.
Additional note: In some cases one might want to use [self isSubclassOf:[RedClass class]] rather than == (though that has some serious pitfalls).

Objective-C initializers and overriding self

I have a question about writing your own init methods in objective-c. I've read a few different books and have seen a couple of ways to do it but the consensus is the right way to do it is like this:
- (id)init
{
self = [super init];
if(self!=nil)
{
}
return self;
}
I'm a little confused about the line "self = [super init]". My understanding is that, there's no guarantee that [super init] will return the class that you expect it to. I think this is called "class clusters". But in the normal case, where it does return the class you expect it to, if I set self to point to a class that is returned to me, aren't I just saying that self is referring to an object of a different class rather than the class that I'm in the init method of?
To summarize, why set self to be the superclass vs the actual class I'm in?
From a blog I read:
The textbook reason is because [super
init] is permitted to do one of three
things:
1) Return its own receiver (the self
pointer doesn't change) with inherited
instance values initialized. 2) Return a
different object with inherited
instance values initialized. 3) Return
nil, indicating failure. In the first
case, the assignment has no effect on
self...
"The assignment has no effect on self" is what confuses me. Why does it have no effect? If I set something = to something else, shouldn't that have an effect?
There are different opinions on the proper way to write -init methods. There are two reasons that would make you think that self = [super init] is a good idea. (The assignment itself isn't anything special; Objective-C considers self to be a hidden parameter of the method, and you can reassign to parameters. The changed self only applies for the remainder of the method.)
Superclass -init returns instance of different class
As you suggested, some classes use the "class cluster" pattern. However, in the most common implementation of this pattern, it's the -alloc method on the base class that is likely to return an instance of a different class, and it's all the -init... methods on the placeholder class that are likely to return an instance of a different class. self = [super init] is not useful here.
Superclass -init returns a different instance of the same class
This is the reason that self = [super init] is recommended. Some classes have logic that allows -init to return a different instance than the one that it was called on. For example, some singleton classes in the Cocoa framework do this. But in almost every case, you need to know this behavior of the superclass in order to properly subclass it. Here's an argument by Wil Shipley that self = [super init] isn't actually very useful, because either [super init] returns self anyway, or the class you're subclassing is sufficiently complicated that reassigning self and then continuing with the initialization won't work anyway.
To summarize, why set self to be the superclass vs the actual class I'm in?
This is the Apple suggested way to do things, specifically due to the case of class clusters, as you say.
In general, you should not worry about the fact that self might be of a different class in the "normal" case.
self simply identifies the object you are, not the class (the class is actually a different object in the runtime). If you think of OO inheritance properties, it is at the same time an object of its class and of its superclass (if it is clear what I am trying to say). There is no contradiction in the "normal" case, since the value of self does not change.
Also, you can think of self as a special pointer to your object. In the cluster case, self can change, that is the reason why it can happen that its class change.
Hope this helps clarifying things. You will also find an interesting reading in this article by Wil Shipley.

Object retain behavior of Objective-C class methods

What's the best practice for retaining and releasing objects passed to class methods?
For instance, if you have a "class variable" declared like so:
static NSString *_myString = nil
...is the right thing to do this:
+ (void)myClassMethod:(NSString *)param {
_myString = param;
}
... which has the drawback that the caller needs to maintain a nonzero retain count on param lest it be released prematurely. Alternatively one could do this:
+ (void)myClassMethod:(NSString *)param {
[_myString autorelease];
_myString = [param retain];
}
...which has the drawback that without a corresponding class-level dealloc call it will leak memory. Or should this sort of class variable chicanery be avoided completely, perhaps with a singleton class that manages the lifetime of these sorts of objects in a more conventional way?
Here are Apple's docs on creating a singleton instance.
The code that I'm working with is the very slick (but still new) Objective Resource project (http://www.iphoneonrails.com/).
Retain and release, absolutely. It's not a leak because the only time when a class's dealloc would be called is when the program ends — at which time the memory will be freed anyway. Doing it the first way would be more hassle and goes against the Cocoa memory-management guidelines.
As for whether it should be a class method or a singleton: Classes themselves generally should not have a lot of independent functionality. They just weren't designed that way in Objective-C, as you can see from the lack of class variables. Class methods should generally deal with creating and managing instances, and sometimes storing shared properties or defaults for all instances. The actual functionality of a class should go into instances. That's the convention in Objective-C.
(Of course, there is no Objective-C God and you're free to ignore conventions, but that's the general wisdom.)
Also, in the case of NSString or any class that has mutable variants (like NSArray or NSDictionary), I'd strongly recommend copying the parameter instead of retaining it. If the string the caller passed you was an NSMutableString, its value could change later, and it will change in your class as well. This is probably not what you want, so I'd advise doing this:
+ (void)myClassMethod:(NSString *)param {
[_myString release];
_myString = [param copy];
}
The copy method makes a copy and sets the retain count to 1, so you're all set as far as retaining the variable is concerned. And, as an extra bonus, if the caller does pass you an NSString, that class is smart enough to know that its value can't change, so it simply retains itself to avoid making a copy of the object. How clever is that?