我对Objective-C中的合成属性有一些疑问.下面是完整的列表,但基本问题是:How does the compiler ensure that the ivars for synthesized properties are properly released, even though my code may or may not include release methods in dealloc?

注:我决定不把这些问题作为单独的问题发布,因为它们是如此密切相关,而且还有一些现有的问题没有真正触及问题的核心.

有些类似的问题:


Setup:考虑具有单个属性的类:

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

Question #1:最基本的情况是:

@implementation Person
@synthesize name;
@end

在这个设置中,我假设每当释放Person对象时,name将自动释放.在我看来,编译器只是简单地将[name release]插入dealloc方法,就好像是我自己键入的一样.对吗?


Question #2:如果我 Select 为这个类编写自己的dealloc方法,而我省略了对[name release]的调用,这会泄漏吗?

@implementation Person
@synthesize name;
- (void)dealloc { [super dealloc]; }
@end

Question #3:如果我 Select 为这个类编写我自己的dealloc方法,并且我include调用[name release],这会导致双重释放吗,因为@synthesize已经为我处理好了?

@implementation Person
@synthesize name;
- (void)dealloc { [name release]; [super dealloc]; }
@end

Question #4:如果我 Select 为这个类编写自己的属性访问器,但我do not编写自己的dealloc方法,name会被泄露吗?

@implementation Person
@dynamic name;
- (void)setName:(NSString *)newName
{
    [newName retain];
    [name release];
    name = newName;
}
@end

Question #5:我有一种感觉(基于经验),上面的none种情况将导致泄漏或双重释放,因为语言设计是为了避免它们.当然,这就提出了"如何"的问题.编译器是否足够聪明,可以跟踪所有可能的情况?如果我做以下事情(请注意,这是一个可笑的例子,只是为了说明我的观点):

void Cleanup(id object) { [object release]; }

@implementation Person
@synthesize name;
- (void)dealloc { Cleanup(name); }
@end

这会欺骗编译器在dealloc方法中再添加[name release]吗?

推荐答案

Q1:

No.@synthesize不会为您修改-dealloc.你得自己动手.

Q2:

是的,它会漏水.与Q1的原因相同.

Q3:

不,它不会双重释放.与Q1的原因相同.

Q4:

是的,它会漏水.与Q1的原因相同.

Q5:

不,它不会双重释放.与Q1的原因相同.


您可以通过覆盖-retain-release-dealloc来判断这一点,以报告正在发生的情况.

#import <Foundation/Foundation.h>

@interface X : NSObject {}
@end
@implementation X
-(oneway void)release {
        NSLog(@"Releasing %p, next count = %d", self, [self retainCount]-1);
        [super release];
}
-(id)retain {
        NSLog(@"Retaining %p, next count = %d", self, [self retainCount]+1);
        return [super retain];
}
-(void)dealloc {
        NSLog(@"Dealloc %p", self);
        [super dealloc];
}
@end

@interface Y : NSObject {
        X* x;
}
@property (nonatomic, retain) X* x;
@end
@implementation Y
@synthesize x;
- (void)dealloc { [x release]; [super dealloc]; }
@end

int main () {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
        Y* y = [[Y alloc] init];
        X* x = [[X alloc] init];
        y.x = x;
        [y release];
        [x release];
        [pool drain];                                                    
        return 0;
}

在Q1、Q2和Q4中,x中的最后-retainCount是1,因此存在泄漏,而在Q3和Q5中,最后-retainCount是0,调用-dealloc,因此没有泄漏.

Objective-c相关问答推荐

UITableViewCell:如何防止蓝色 Select ​​背景不带 isSelected 属性?

应用程序终止时处理推送通知

在 ARC 之后,我应该为调度队列使用什么属性?

当我从导航控制器推送时如何隐藏导航栏?

UICollectionView 标头未显示

如何在 iPhone 上画出讲话泡泡?

arc4random 和 arc4random_uniform 有什么区别?

当用户返回视图控制器时如何取消 Select uitableview 单元格

iPhone - 什么是重用标识符(UITableViewCell)?

自定义 UINavigationBar 背景

AdMob 因 [GADObjectPrivate changeState:] 崩溃:无法识别的 Select 器

在字符串Objective-c中连接字符串

Objective C 中的调用方法或发送消息

在 UITableView 中更改复选标记的 colored颜色

UIView: opaque vs. alpha vs. opacity

请求访问相机胶卷的权限

UIScrollView contentSize 不起作用

Block 隐式保留'self';明确提及touch以表明这是预期行为

Xcode 在调试时判断表达式

Unwind Segue 在 iOS 8 中不起作用