【问题标题】:Question on retain attribute with @property and @synthesize关于使用 @property 和 @synthesize 保留属性的问题
【发布时间】:2010-12-31 03:08:17
【问题描述】:

我对 Objective-C 编码还是很陌生(正如这个问题所证明的那样),我想我还没有完全理解在 @property 声明中使用 retain 属性是如何工作的。

这是一个示例类:

@interface Foo : NSObject {
    NSMutableArray *myArray; 
}

@property (retain) NSMutableArray *myArray;

我的理解是,在@property 声明中添加retain 属性(并在实现文件中使用必要的@synthesize 声明)基本上将为我执行以下setter 和getter:

- (void)setMyArray:(NSMutableArray *)newArray {
    myArray = [[NSMutableArray alloc] initWithArray:newArray];
    [newArray release];
}

- (NSMutableArray *)myArray {
    return myArray;
}

这是准确的还是我对保留属性的工作方式有误?

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    添加retain属性实际上会生成这段代码:

    - (void)setMyArray:(NSMutableArray *)newArray {
        [newArray retain];
        [myArray release];
        myArray = newArray;
    }
    
    - (NSMutableArray *)myArray {
        return myArray;
    }
    

    retain 方法在 newArray 上调用 release 之前在 old 值上的原因是如果 newArray 和 myArray 是同一个对象,则数组会在它之前被释放再次保留。

    【讨论】:

    • 那么如果我自己重写setter方法,我应该遵循retain和release这种格式吗?
    • @cpjolicoeur:这取决于实际的实现,使用锁来防止线程问题更加复杂。
    • 是的,这正是编译器生成它的方式(我一直在尝试找到对此的引用,但我现在似乎找不到它)
    • 我相信 setter 调用被 if (newArray == myArray) 包围是为了在分配相同对象时获得一点性能,但这基本上是一个实现细节。
    • 你确定返回[[myArray retain] autorelease]; .如果您继续分配新对象,这不会导致大量对象挂在AutoReleasePool 中吗?如果self 被释放,那么myArray 仍然会一直存在直到池被杀死,即使程序中没有其他任何东西引用它们。
    【解决方案2】:

    要做好真的很难。看看 Matt Gallagher 撰写的关于 Cocoa with Love 的文章 Memory and thread-safe custom property methods

    这是一个有效的实现,很大程度上受到that excellent article的启发。

    - (void)setSomeString:(NSString *)aString {
        @synchronized(self)
        {
            if (someString != aString) // not necessary, but might improve
                                       // performance quite a bit
            {
                [aString retain];
                [someString release];
                someString = aString;
            }
        }
    }
    
    - (NSString *)someString {
        @synchronized(self)
        {
            id result = [someString retain];
        }
        return [result autorelease];
    }
    

    【讨论】:

    【解决方案3】:

    retain 不会复制新值。它将保留新值并释放旧值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-06
      • 1970-01-01
      • 2011-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多