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

nutthick

macrumors newbie
Original poster
Apr 11, 2007
26
0
I'm trying to write a class method with the following header.

Code:
@interface Point3D : NSObject
{
	float pointX;
	float pointY;
	float pointZ;
}

+ (id)initWithPointX:(float)x Y:(float)y Z:(float)z;
- (float)x;
- (float)y;
- (float)z;

@end

and the code as follows.

Code:
+ (id)initWithPointX:(float)x Y:(float)y Z:(float)z
{
	[super init];

	pointX = x;
	pointY = y;
	pointZ = z;
	
	return self;
}

- (float)x
{
	return pointX;
}

- (float)y
{
	return pointY;
}

- (float)z
{
	return pointZ;
}

However, I keep getting the following warnings in the initWithPointX method

Code:
warning: instance variable 'pointX' accessed in a class method
warning: instance variable 'pointY' accessed in a class method
warning: instance variable 'pointZ' accessed in a class method

When I run the program it crashes with

Code:
The Debugger has exited due to signal 11 (SIGSEGV).The Debugger has exited due to signal 11 (SIGSEGV).

I've been Googling for a Class Method example, but can't find one. Can anyone help?

This is related to my previous post NSMutableArray and Pointers for some context.

Thanks
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
1) Anything named init should not be a class method.

2) A class method cannot access instance variables: they can only be accessed by instances (they simply don't exist at the class level).

It appears you are trying to write a factory method that will return an autoreleased instance of the class. One potential solution is below:

Code:
+ (id)pointWithX:(float)x Y:(float)y Z:(float)z
{
return ([[[Point3D alloc] initWithPointX:x Y:y Z:z] autorelease]);
}
 
- (id)initWithPointX:(float)x Y:(float)y Z:(float)z
{
	if (self = [super init])
 {
	pointX = x;
	pointY = y;
	pointZ = z;
	
	return self;
}
return nil;
}

- (float)x
{
	return pointX;
}

- (float)y
{
	return pointY;
}

- (float)z
{
	return pointZ;
}
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
I'm trying to write a class method with the following header.

Code:
@interface Point3D : NSObject
{
	float pointX;
	float pointY;
	float pointZ;
}

+ (id)initWithPointX:(float)x Y:(float)y Z:(float)z;
- (float)x;
- (float)y;
- (float)z;

@end

and the code as follows.

Code:
+ (id)initWithPointX:(float)x Y:(float)y Z:(float)z
{
	[super init];

	pointX = x;
	pointY = y;
	pointZ = z;
	
	return self;
}

Could you, just for yourself, try to write down as clearly as possible what a class is and what an object is and what the difference between these two is? Once you've done that, could you try to give the reasons why in every class "alloc" is a class method, while the various init methods are all instance methods?

I personally think it helps a lot if you try to understand something, and writing it down often helps with that, instead of just blundering ahead until you get something that compiles.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
It appears you are trying to write a factory method that will return an autoreleased instance of the class. One potential solution is below:

Code:
+ (id)pointWithX:(float)x Y:(float)y Z:(float)z
{
return ([[[Point3D alloc] initWithPointX:x Y:y Z:z] autorelease]);
}

This brings up something that I have been curious about. I just read the NSObject protocol documentation for retain, release, and autorelease, and understand that init and copy methods should return an object with a retain count of 1, and factory methods should retain an autoreleased object. What should the retain count be of the autoreleased object? 1, so when the pool calls release the retain count is 0?

-Lee
 

Littleodie914

macrumors 68000
Jun 9, 2004
1,813
8
Rochester, NY
This brings up something that I have been curious about. I just read the NSObject protocol documentation for retain, release, and autorelease, and understand that init and copy methods should return an object with a retain count of 1, and factory methods should retain an autoreleased object. What should the retain count be of the autoreleased object? 1, so when the pool calls release the retain count is 0?

-Lee
I think the retain count should be 1, since you're allocating space for a new object, then initializing it.

Edit: Wait, maybe not. If you create an autoreleased object in a scope, when that scope is exited, the object is automatically autoreleased unless you specifically retain it. So I would say it's 0?
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
I think the retain count should be 1, since you're allocating space for a new object, then initializing it.

Edit: Wait, maybe not. If you create an autoreleased object in a scope, when that scope is exited, the object is automatically autoreleased unless you specifically retain it. So I would say it's 0?

"autorelease" doesn't release an object. It tells the active autorelease pool "please release this object when you (the autorelease pool) go out of scope". So a method creating an autoreleased object will: Call alloc (retain count = 1), call init (retain count stays = 1), call autorelease (retain count stays 1, autorelease pool will release it some time later).

So if you do nothing else, there will be another "release" call when the autorelease pool is closed down, which will change the retain count to zero and destroy the object. If you decide that you want to keep the object around for half an hour, you call retain (retain count = 2), then the autorelease pool will release it at some point in time (retain count = 1), and half an hour later your own code might release it (retain count = 0, object gets destroyed).

You can never have an object with a retain count = 0.
 

whooleytoo

macrumors 604
Aug 2, 2002
6,607
716
Cork, Ireland.
and factory methods should retain an autoreleased object.

Gnasher's explanation above is correct - but I don't understand the sentence above - do you mean return, instead of retain?

Autorelease is used when returning any object from a function/method which that function/method created. And if you intend to use that object outside the calling scope, you need to retain it (and, of course, ultimately release it again when done with it).
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
Gnasher's explanation above is correct - but I don't understand the sentence above - do you mean return, instead of retain?

Autorelease is used when returning any object from a function/method which that function/method created. And if you intend to use that object outside the calling scope, you need to retain it (and, of course, ultimately release it again when done with it).

Just at typo, i meant return. gnasher729 covered what I was curious about, which was more or less if the object returned by a factory method should have a retain count of 0 or 1.

-Lee
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
Gnasher's explanation above is correct - but I don't understand the sentence above - do you mean return, instead of retain?

Sometimes both :D Lets say an object that represents a window has a method returning the window title as an NSString*. Lets say the window has created that title with a retain count of 1, it keeps hold of the title and releases it when the window is deleted. You would then retain the title, autorelease it, and return the retained title. The retain count is now 2, but one retain will go away when the autorelease pool is closed. However, if you delete the window, the retain + autorelease made sure that the title survives deleting the window (until the autorelease pool releases the title).
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.