0

好吧,我在目标 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 的对象,然后在一段时间后调用该对象的方法 1([对象方法 1]),我得到运行时错误(错误告诉我 playBut 是 dealloc,但我认为 playBut 的保留计数 = 1)。所以我有一些问题:

  1. 可能吗 ?
  2. 为什么垃圾收集器会释放 playBut 如果它的保留计数 = 1?(因为我不调用 [playBut release];
  3. 如何初始化类属性?

我熟悉 C++ 和 actionScript,但我一生中第一次看到垃圾收集器释放了类属性。我使用非ARC。这对我很重要。感谢您的关注和解答。

4

2 回答 2

2

[UIButton buttonWithType:]返回一个autoreleased对象。它将在您调用它的范围的生命周期内保持有效,即,initWithFrame:但自动释放池可以在此之后回收它。你应该在你的初始化选择器中说:

playBut = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];

然后将其发送到您的dealloc

[playBut release];

现在,如果您将playBut作为孩子添加到另一个UIView,该视图将保留孩子并且您不需要,只要您只在超级视图的生命周期内使用它。这是一个正常的模式。您可以更进一步,将 a 分配tag给 playBut 然后使用viewWithTag:在需要时找到您的UIButton

于 2013-02-16T17:41:20.100 回答
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)。在这里查看我的答案: 我应该在接口中声明变量还是在 Objective-C 弧中使用属性?

至于您使用 UIButtons 的特定示例,它们通常会直接添加到 UI 中,它会为您保留,因此您不会遇到这种情况。这就是为什么IBOutlets通常声明为weak(ARC) 或assign(nonARC)。

于 2013-02-16T17:46:21.813 回答