1
  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;
}
Rob
  • 371,891
  • 67
  • 713
  • 902
Patt Mehta
  • 3,862
  • 1
  • 19
  • 44
  • 2
    As an aside, Apple generally advises that (a) you don't declare an explicit ivar to back your property, but let the compiler do that for you; (b) you don't need `@synthesize` line any more, and if you did, best practice would be `@synthesize name = _name;` so that the ivar would be `_name`, to avoid possible confusion; (c) when dealing with strings, it's safer, generally, to use `copy` instead of `retain` so you don't have to fear it mutating on you. – Rob Jul 23 '13 at 19:23
  • Please provide Objective-C docs for (a) and (b) for further reading. Thanks! – Patt Mehta Jul 23 '13 at 20:06
  • 1
    WWDC 2012 session #405 - Modern Objective-C, roughly 10 or 11 minutes into the video. (Unfortunately, because of Apple's security problems, you might not be able to access the WWDC videos right now.) But this video describes it in some detail. – Rob Jul 23 '13 at 20:31
  • 1
    In the comments below, you mention that you're using GNUStep on Windows. In that case, if you're using the standard GNUStep configuration, while the counsel to let the compiler synthesize the accessor methods still stands, you may have to include the ivar that backs your property, and you may have to include the `@synthesize` line, too. – Rob Jul 24 '13 at 14:31

2 Answers2

3

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.

Brian Walker
  • 8,108
  • 2
  • 30
  • 34
  • |"The getter should return an autoreleased object." - In this manner - `return [name autorelease];` or, in this manner - `- (void) dealloc {[name release]; [super dealloc];}` – Patt Mehta Jul 23 '13 at 20:27
  • 1
    @GLES No, don't `autorelease` in the getter. (That's either a typo in Brian's answer or he was talking about Matt's discussion of `atomic` properties, in which you both `retain` and `autorelease`; but _do not autorelease without retain_). And contrary to the possible inference of Matt's article, using atomic properties does _not_ ensure thread safety. – Rob Jul 23 '13 at 20:40
  • I read that already - "atomic" does not make any guarantees about thread safety @http://stackoverflow.com/questions/588866/atomic-vs-nonatomic-properties. Thanks for the valuable suggestions! – Patt Mehta Jul 23 '13 at 20:46
  • @BrianWalker +1 nice clarification. – Rob Jul 24 '13 at 16:27
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
Rob
  • 371,891
  • 67
  • 713
  • 902
  • |"An autorelease is, effectively, a deferred release, so it's not appropriate for either the getter or the setter to do so." - What is the appropriate way then; releasing the ivar inside dealloc? |"Sure, the setter would release the old object, but it certainly shouldn't be doing an autorelease of the new object." - So, the correct way is to `copy` `someString` and then release it, or, simply `copy` `someString` without affecting it? – Patt Mehta Jul 23 '13 at 20:18
  • 1
    @GLES Yes, if you're writing non-ARC code, release the ivar in `dealloc`. (But you really should be writing ARC code, and this is done for you.) If you're writing your own setter (but don't do that unless you have a compelling reason to do so), if it's a `retain` property, the setter would `release` the old value's object and `retain` the new value's object. If it's a `copy` property, the setter would `release` the old one and `copy` the new one. – Rob Jul 23 '13 at 20:37
  • OK, but in non-ARC what is the correct way to use `property/synthesize pair` for an ivar (such as the `name` ivar in the class I've defined)? Please provide the code or SO links. Thanks in advance! (I'm using `GNUstep` to compile Objective-C code on Windows, so, the Xcode tools are not for me). – Patt Mehta Jul 24 '13 at 07:52
  • 1
    @GLES I've updated my answer with code samples. Because you're using GNUStep, it's a little more complicated because it depends upon which compiler you're using. In Xcode, backing ivars are optional (and recommended to be excluded) and synthesize lines are optional, too. gcc doesn't synthesize ivars for you and the `@synthesize` statement is not optional, so you have to explicitly write that code. But the accessor methods will be synthesized for you, so you don't need to write those. – Rob Jul 24 '13 at 14:25