Writing a Class Method

Discussion in 'Mac Programming' started by nutthick, Sep 11, 2008.

  1. macrumors newbie

    Joined:
    Apr 11, 2007
    #1
    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
     
  2. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    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;
    }
    
     
  3. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #3
     
  4. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #4
    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
     
  5. macrumors 68000

    Littleodie914

    Joined:
    Jun 9, 2004
    Location:
    Rochester, NY
    #5
    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?
     
  6. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #6
    "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.
     
  7. macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #7
    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).
     
  8. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #8
    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
     
  9. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #9
    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).
     
  10. thread starter macrumors newbie

    Joined:
    Apr 11, 2007
    #10
    robbieduncan - Thanks for your help, I'll give it a try.
     

Share This Page