Question

  1. In the getter function (that is automatically generated) for the property name, is the object returned as follows?

    [self.name autorelease]; 
    return self.name;
    
  2. In the setter function (also automatically generated), is the retained object autoreleased? -

    - (void) setName : (NSString *) someString {
        [someString retain];
        [name release];
        name = someString;
        /* [someString autorelease]; */ // performed internally?
    }
    

#import<Foundation/Foundation.h>

@interface Dog : NSObject
{@private NSString * name;}
@property (nonatomic,retain) NSString * name;
@end

@implementation Dog
@synthesize name;
- (id) init {
    self = [super init];
    if(self) {}
    return self;
}
@end

int main(int argc, char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    Dog * d = [[Dog alloc] init];
    [d setName:@"Scooby"];
    NSLog(@"Dog's name is: %@",[d name]);
    [d release];
    [pool drain];
    return 0;
}
Was it helpful?

Solution 2

In answer to your two questions:

  1. The getter should not autorelease the object.

  2. The setter should not autorelease the new value's object pointed to by someString.

An autorelease is, effectively, a deferred release, so it's not appropriate for either the getter or the setter to do so. Sure, the setter would release the old object, but it certainly shouldn't be doing an autorelease of the new object.


By the way, three final observations:

  • You should not write your own setters and getters unless there's some compelling need to do so. If you just wanted to understand what they're doing, that's fine, but in practice, we rarely write our own accessor methods.

  • Furthermore, I'd heartily encourage you to use ARC (if you can).

  • If using Xcode and using manual reference counting for some reason, definitely run your code through the static analyzer ("Analyze" on the Xcode "Product" menu), as it would point out many of these routine mistakes with autorelease.


If using gcc with GNUStep, your Dog class might look like:

@interface Dog : NSObject
{
    NSString *_name;
}

@property (nonatomic, copy) NSString *name;

@end

@implementation Dog

@synthesize name = _name;

- (id)init
{
    self = [super init];
    if (self) {
        _name = nil;
    }
    return self;
}

- (void)dealloc
{
    [_name release];
    [super dealloc];
}

@end

Note, no accessor methods defined (they're synthesized for me).

While gcc doesn't support it, if you were using a newer compiler, you could omit the ivar declaration and the @synthesize line:

@interface Dog : NSObject

@property (nonatomic, copy) NSString *name;

@end

@implementation Dog

- (id)init
{
    self = [super init];
    if (self) {
        _name = nil;
    }
    return self;
}

- (void)dealloc
{
    [_name release];
    [super dealloc];
}

@end

Or if using ARC, you could even omit the init method (because ARC initializes objects to nil) and the dealloc method (because ARC obviously automatically releases objects):

@interface Dog : NSObject

@property (nonatomic, copy) NSString *name;

@end

@implementation Dog

@end

OTHER TIPS

No. Autoreleasing where you ask would release name and cause an access violation since the object in name would not be retained. The getter could return an autoreleased object if it retains the object before returning it: return [[name retain] autorelease];. This might need to be done to support accessing from multiple threads but some sort of thread synchronization needs to be in the getter and setter in that case.

For your code to be correct in non-ARC it needs to have a dealloc method that releases name.

- (void)dealloc
{
    [name release];
    [super dealloc];
}

There is some discussion of the topic of the auto-generated code here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top