关于目标c中的init属性类

时间:2013-02-16 17:34:06

标签: objective-c cocoa-touch

好 我在目标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 )。 所以我有一些问题:

  1. 有可能吗?
  2. 为什么垃圾收集器dealloces playBut如果它的retain count = 1?(因为我没有调用[playBut release];
  3. 如何初始化类属性?
  4. 我熟悉C ++和ActionScript,但我在生活中第一次看到垃圾收集器释放了类属性。 我用非ARC。 这对我很重要。 感谢您的关注和答案。

2 个答案:

答案 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)的原因。