objective-c - 为声明的属性合成了哪些等效代码?

标签 objective-c gcc memory-management

自动合成后的 getter 和 setter 方法体到底是什么样子的?

到目前为止,我从官方文档中只发现了推荐的实现技术,但是没有关于编译器在合成过程中使用了哪些技术的消息:http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAccessorMethods.html#//apple_ref/doc/uid/TP40003539-SW5

一些技术推荐包含autorelease 消息的实现,这对于多线程编程来说不是很安全。我只是想知道自动生成的代码是否遵循某些建议的实现。


例如:

.h

@interface AClass: NSObject{}
    @property (nonatomic, retain) AnotherClass *aProp;
@end

.m

@implementation AClass
    @synthesize aProp

-(id) init {
    if ((self = [super init])) {
        self.aProp = [[AnotherClass alloc] init];    // setter invocation
    }
    return self;
}

-(AnotherClass *) aMethod {
    return self.aProp;     // getter invocation
}
@end

编译器为 aProp 生成的等效访问器代码片段是什么?

-(AnotherClass *) aProp {
    // getter body
}

-(void) setAProp: (AnotherClass *) {
    // setter body
}

最佳答案

将属性声明为 nonatomic 时,您将获得以下信息:

// .h
@property (nonatomic, retain) id ivar;

// .m
- (id)ivar {
    return ivar;
}

- (void)setIvar:(id)newValue {
    if (ivar != newValue) {  // this check is mandatory
        [ivar release];
        ivar = [newValue retain];
    }
}

注意检查 ivar != newValue。如果它不存在,ivar 可能会在 release 之后被释放,并且下面的 retain 会导致内存访问错误。

当您使用copy 声明您的属性时,代码看起来几乎相同,retain 替换为copy

对于assign,就更简单了:

- (void)setIvar:(id)newValue {
    ivar = newValue;
}

现在,当您将您的属性声明为 atomic(这是默认属性)时,事情会变得稍微复杂一些。 Apple 的一位工程师在开发论坛上发布了类似于下面的片段:

- (id)ivar {
    @synchronized (self) {
        return [[self->ivar retain] autorelease];
    }
}

- (void)setIvar:(id)newValue {
    @synchronized (self) {
        if (newValue != self->ivar) {
            [self->ivar release];
            self->ivar = newValue;
            [self->ivar retain];
        }
    }
}

请注意两种方法中的 @synchronized block 和 getter 中的附加 retain-autorelease。这两件事确保您将获得以前的值(保留和自动释放)或一个新值,以防在您尝试读取值时某个线程更改了该值。

关于objective-c - 为声明的属性合成了哪些等效代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5350563/

相关文章:

ios - 在 Swift 中读取 UIApplicationLaunchOptionsURLKey

ios - ViewModel 完成操作时在 ViewController 中的通知

c - gcc 5编译fork()返回父pid 0吗?

c++ - GCC/GCOV 为使用 throw()/noexcept 的函数生成的不同分支覆盖

c - 如何将链表的头节点地址存储在文件中并稍后检索

C:动态大小的二维字符串数组

ios - 如何显示未完全加载的图像的缩略图

objective-c - 如何在多个类中使用同一个类别?

windows - 使通配符目标始终得到无所事事

ios - 我如何获得 CPU、GPU、使用的磁盘、Apple 设备中的免费信息