属性/合成对 - 做getters和setter自动释放对象?

时间:2013-07-23 16:43:40

标签: objective-c gnustep

  1. 在属性name的getter函数(自动生成)中,对象是否按如下方式返回?

    [self.name autorelease]; 
    return self.name;
    
  2. 在setter函数(也是自动生成的)中,是retain ed对象autorelease d? -

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

  3. #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;
    }
    

2 个答案:

答案 0 :(得分:3)

没有。您要求的自动释放将释放名称并导致访问冲突,因为名称中的对象不会被保留。如果getter在返回之前保留了对象,则它可以返回一个自动释放的对象:return [[name retain] autorelease] ;.可能需要这样做才能支持从多个线程进行访问,但在这种情况下,某些线程同步需要在getter和setter中。

为了使您的代码在非ARC中正确,它需要一个释放名称的dealloc方法。

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

对自动生成的代码here的主题进行了一些讨论。

答案 1 :(得分:2)

回答你的两个问题:

  1. getter不应该autorelease该对象。

  2. setter不应autorelease someString指向的新值对象。

  3. autorelease实际上是延迟release,因此不适合getter或setter这样做。当然,setter会release旧对象,但肯定不应该对新对象进行autorelease


    顺便提一下,最后三个观察结果:

    • 除非有一些迫切的需要,否则你不应该写自己的定位器和吸气剂。如果你只是想了解他们正在做什么,那很好,但在实践中,我们很少编写自己的访问方法。

    • 此外,我衷心鼓励您使用ARC(如果可以的话)。

    • 如果出于某种原因使用Xcode并使用手动引用计数,请务必通过静态分析器运行代码(Xcode“Product”菜单上的“Analyze”),因为它会指出许多常规错误。 autorelease


    如果在GNUStep中使用gcc,您的Dog类可能如下所示:

    @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
    

    注意,没有定义访问器方法(它们是为我合成的)。

    虽然gcc不支持它,但如果您使用的是较新的编译器,则可以省略ivar声明和@synthesize行:

    @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
    

    或者如果使用ARC,您甚至可以省略init方法(因为ARC将对象初始化为nil)和dealloc方法(因为ARC显然会自动释放对象):

    @interface Dog : NSObject
    
    @property (nonatomic, copy) NSString *name;
    
    @end
    
    @implementation Dog
    
    @end