标题中有以下内容:
@property (nonatomic, retain) UIView *overlay;
在实施中:
@synthesize overlay;
然后:
UIView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
self.overlay = tempOverlay;
[tempOverlay release];
上面的tempOverlay
变量不是不必要的吗?我不能这样做:
self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
答案 0 :(得分:11)
合成的保留setter看起来像:
- (void)setValue: (id)newValue
{
if (value != newValue)
{
[value release];
value = newValue;
[value retain];
}
}
在您的情况下,您有两种有效的方法:
1)创建一个temp var,alloc / init(=保留),设置为property,release。
IView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
self.overlay = tempOverlay;
[tempOverlay release];
2)没有temp var,直接设置为ivar。
overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
更新:
如果使用方法2),则必须通过释放之前可能存在的任何先前值(如果需要)来显式处理剩余的内存管理(不仅仅是保留)。如果只在init
中完成一次(例如),您只需将[overlay release];
放入dealloc
。
答案 1 :(得分:2)
使用retain
属性指定应在新对象上调用retain
,并将之前的值发送为release
。
所以在你的第二个代码块中,对象的保留计数将变为2,因为你不再释放它,并且setter保留它。这不太可能是你想要的。
答案 2 :(得分:1)
如果将对象直接分配给属性,则仍必须将其释放:
self.overlay = [[[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)] autorelease];
答案 3 :(得分:1)
由于您的属性定义为(保留)您使用合成setter设置的任何实例(通过self.overlay语法)将自动发送保留消息:
// You're alloc'ing and init'ing an object instance, which returns an
// instance with a retainCount of 1.
UIView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
// The overlay property is defined with (retain), so when you assign the new
// instance to this property, it'll automatically invoke the synthesized setter,
// which will send it a retain message. Your instance now has a retain count of 2.
self.overlay = tempOverlay;
// Send a release message, dropping the retain count to 1.
[tempOverlay release];
如果你这样做:
self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
您的叠加层的保留计数为2,这可能会导致应用程序中某个位置出现泄漏。
答案 4 :(得分:0)
感谢您的所有答案。我收到了一些相互矛盾的声明,所以我在UITableViewController
中测试了以下内容:
- (id)initWithStyle:(UITableViewStyle)style {
if ((self = [super initWithStyle:style])) {
NSLog(@"count: %d", [overlay retainCount]);
self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
NSLog(@"count: %d", [overlay retainCount]);
[overlay release]; NSLog(@"released once");
NSLog(@"count: %d", [overlay retainCount]);
[overlay release]; NSLog(@"released twice");
NSLog(@"count: %d", [overlay retainCount]);
}
return self;
}
我得到了以下控制台输出:
有时它运行良好:
count: 0
count: 2
released once
count: 1
released twice
count: 1
其他时候它崩溃了:
count: 0
count: 2
released once
count: 1
released twice
Program received signal: “EXC_BAD_ACCESS”.
我知道使用tempOverlay
的方法是正确的。它看起来很麻烦,但我更喜欢它autorelease
,因为我不明白autorelease
是如何工作的或何时被调用。有一件事是肯定的。上面的代码是错误的,因为我不希望overlay
的保留计数为2。
奇怪的是我无法释放它两次。即使它没有崩溃,保留计数也不会减少。
无论如何,我想我现在会坚持使用tempOverlay
。
答案 5 :(得分:-2)
是的,您可以直接将新创建的对象分配给overlay
对象。如果您愿意,您可以通过打印出对象的保留计数来证明自己
NSLog(@"count: %d", [overlay retainCount]);