Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

CMT

macrumors regular
Original poster
Aug 24, 2009
104
10
Just a simple beginner question, what's the difference between:

Code:
#import <Cocoa/Cocoa.h>
#import "ClassOne.h"


@interface ClassTwo : NSObject {
	
	ClassOne *objectFromClassOne;
}

-(void)doSomething;

@end

@implementation ClassTwo

-(void)doSomething {
	
	objectFromClassOne = [[ClassOne alloc] init];
	
	// ...
	
	[objectFromClassOne release];
	
}

@end

And:

Code:
#import <Cocoa/Cocoa.h>
#import "ClassOne.h"


@interface ClassTwo : NSObject {
	
}

-(void)doSomething;

@end

@implementation ClassTwo

-(void)doSomething {
	
	ClassOne *objectFromClassOne = [[ClassOne alloc] init];
	
	// ...
	
	[objectFromClassOne release];
	
}

@end

If any…

Thanks!
 
In the first example objectFromClassOne is an instance variable. Meaning all methods in ClassTwo can access it. This means that it is usually a very bad idea to release and destroy that object in any method other than -dealloc. This could be a fatal flaw, and should be avoided. Often by just moving the [objectFromClassOne release] to the -dealloc method.

In example 2, objectFromClassOne is just an object in the -doSomething method, and apparently gets destroyed at the end of the -doSomething method.
 
In the first example objectFromClassOne is an instance variable. Meaning all methods in ClassTwo can access it. This means that it is usually a very bad idea to release and destroy that object in any method other than -dealloc. This could be a fatal flaw, and should be avoided. Often by just moving the [objectFromClassOne release] to the -dealloc method.
To clarify, instance variables are meant to be used as persistent data content of an object instance. Creating and releasing an instance variable within a method makes little sense.

If you do release an instance variable, the best way to avoid later problems is to then set its pointer value to nil so that other methods do not use a deallocated or incorrect pointer.

In example 2, objectFromClassOne is just an object in the -doSomething method, and apparently gets destroyed at the end of the -doSomething method.
As well it should be in order to avoid a memory leak.
 
Thank you jared_kipe and Sydde.

In my case, ClassTwo would be an Controller class which connects a View to a Model. This model does some math operations and returns an output NSString *.

So, I'd prefer to do it like the first example, where ClassOne would be the model. But as far as I understand, when I do 'Model *model' (ivar), I'm not creating an object. (tell me if I'm wrong) So in order to use it I have to do [[model alloc] init] somewhere.

Here's the problem: I include this on the same doSomething method, then each time I call the method I'll be creating an object? And, If I create it but then release, like I wrote in the previous post 1st example, will I be able to create another (with the same pointer I declared)?

Once again, thanks a lot.
 
A declaration like
Code:
Model   *model;
simply reserves space for a pointer. In the case of an instance variable (the first example), you can be fairly certain that its initial value will be nil. In the case of a method variable (the second example), the pointer lives on the stack, so its value is always unknown until you initialize it with something (as in creating an object).

The second form is generally preferred for temporary objects, as long as you remember to release them. If you do use the first form, you should set the ivar pointer to nil after you release it, just to be safe.
 
Thanks Sydde, now I got it.

Best wishes
 
The second form is generally preferred for temporary objects, as long as you remember to release them. If you do use the first form, you should set the ivar pointer to nil after you release it, just to be safe.

I'm sort of torn on this myself. Setting it to nil always looks like a good idea at first, but it can make debugging much harder. NSZombie won't work, and what would have been a crash with a useful backtrace will turn into a silent return of nil, which could cause havoc elsewhere in your app.
 
Just a tip: You were using names for instance variables that are not recognisable as such. Follow a coding style where instance variables are instantly recognisable in your code. People use different styles, like objectFromClassOne_ or _ objectFromClassOne or m_ objectFromClassOne. If you follow this consequently then you know immediately what an identifier in your code means.
 
Thank you jared_kipe and Sydde.

In my case, ClassTwo would be an Controller class which connects a View to a Model. This model does some math operations and returns an output NSString *.

So, I'd prefer to do it like the first example, where ClassOne would be the model. But as far as I understand, when I do 'Model *model' (ivar), I'm not creating an object. (tell me if I'm wrong) So in order to use it I have to do [[model alloc] init] somewhere.

Here's the problem: I include this on the same doSomething method, then each time I call the method I'll be creating an object? And, If I create it but then release, like I wrote in the previous post 1st example, will I be able to create another (with the same pointer I declared)?

Once again, thanks a lot.

In almost any case, your model object would be created in -init or through some action from the user. Such as the user types in something and presses a button which fires off a method that takes the typed input and creates a new model object with that input.
 
In almost any case, your model object would be created in -init or through some action from the user. Such as the user types in something and presses a button which fires off a method that takes the typed input and creates a new model object with that input.

Aha, perfect for what I need. I'll create the the model inside the controller -init overwrite

Code:
-(id)init {
	if (self = [super init]) {
		myModelObject = [[Model alloc]init];
	}
	return self;
}

and destroy it in -dealloc.

Code:
-(void)dealloc {
	[myModelObject release];
	[super dealloc];
}

That way no memory will leak.

Thanks!

Best regards
 
Just a tip: You were using names for instance variables that are not recognisable as such. Follow a coding style where instance variables are instantly recognisable in your code. People use different styles, like objectFromClassOne_ or _ objectFromClassOne or m_ objectFromClassOne. If you follow this consequently then you know immediately what an identifier in your code means.

I believe Apple recommends against using a leading underscore on ivar names because thats what they use for private ivars and it could lead to conflicts (when defining new ivars in your own subclass of a Cocoa class, for example).
 
I believe Apple recommends against using a leading underscore on ivar names because thats what they use for private ivars and it could lead to conflicts (when defining new ivars in your own subclass of a Cocoa class, for example).

Yep:
Don’t use the underscore character as a prefix for your private methods. Apple reserves this convention.
 
Only for methods, Apple says its ok for ivars.

Where do they say that? Use the debugger to spy on virtually any Cocoa object and you will see a ton of private ivars with underscore prefixes (i.e. ones that Apple created that you want to avoid conflict with). Not to mention that an ivar with an underscore prefix would logically lead to an accessor method with an underscore prefix, especially if you are using ObjC 2.0 properties.
 
Only for methods, Apple says its ok for ivars.

Well they don't say it there specifically but I would assume to not use it for ivars as well. I've personally seen conflicts with this before, so I avoid it entirely now.
 
Either they changed their style guidelines fairly recently or I'm going crazy. In the same section where they say not to name private method names with a proceding underscore, they used to say that you were free to do so on private instance variables.

None the less, they do indicate that if you plan on having private instance variables you should use the @private keyword. The reason for this is that only instances of that class itself can access those ivars. Not even subclasses.

On the iPhone and 64bit Mac OS you can even have dynamic ivars that have the same name, but are not the same object or value for subclasses.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.