好 我在目标c中对初始化类属性有一些麻烦。我已经阅读了很多信息,但我没有找到答案。 所以我举个例子。 1)
//Ex_1.h
@interface Ex_1: UIView {
IBOutlet UIButton *playBut;
}
@property(retain, nonatomic) IBOutlet UIButton *playBut;
-(void) method1;
@end
//Ex_1.m
@implementation Ex_1
@synthesize playBut;
-(id) initWithFrame:(CGRect)frame {
self = [super initWithFrame : frame];
if (self != nil)
playBut = [UIButton buttonWithType:UIButtonTypeRoundedRect]; //retainCount of playBut = 1;
return self;
}
-(void) method1 {
[playBut setTitle:@"pause" forState:UIControlStateNormal];
}
@end
我的主要程序首先我是Ex_1的init对象然后经过一段时间调用此对象的method1([object method1])并且我得到运行时错误(错误告诉我playBut是dealloc,但我认为playBut的保留计数= 1 )。 所以我有一些问题:
我熟悉C ++和ActionScript,但我在生活中第一次看到垃圾收集器释放了类属性。 我用非ARC。 这对我很重要。 感谢您的关注和答案。
答案 0 :(得分:2)
[UIButton buttonWithType:]
会返回autoreleased
个对象。它将在您调用它的范围的生命周期内保持活动状态,即initWithFrame:
,但自动释放池可以在此之后回收它。你应该在你的init选择器中说:
playBut = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
然后在dealloc
:
[playBut release];
现在,如果你要将playBut
作为一个孩子添加到另一个UIView
,那么该视图会保留孩子并且您不需要,只要您在此期间仅使用它超级视图的生命周期。这是正常模式。您可以进一步指定tag
进行播放,然后使用viewWithTag:在需要时找到UIButton
。
答案 1 :(得分:1)
您可能会感到困惑,因为您的财产声明包含retain
。但是,您可以在此处直接分配给您的iVar:
playBut = [UIButton buttonWithType:UIButtonTypeRoundedRect]; //retainCount of playBut = 1;
因此不利用属性设置器,因此它不会保留给您。
所以:
self.playBut = [UIButton buttonWithType:UIButtonTypeRoundedRect];
或者:
playBut = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
在这两者中,使用self.playBut 远更好 - 你应该一直使用属性及其访问者,除非你有充分的理由不这样做。并且无需单独声明iVar(或者@synthesize这些天)。在这里看到我的答案: Should I declare variables in interface or using property in objective-c arc?
关于使用UIButton的特定示例,它们通常会直接添加到UI中,这会为您保留,因此您不会遇到此问题。这就是IBOutlets
通常被声明为weak
(ARC)或assign
(非ARC)的原因。