协议记忆

时间:2011-05-15 10:47:59

标签: objective-c memory-management

我很抱歉转发。真正让我烦恼的是,如果属性保留应该在以下情况下释放:
情况1 :(下面的代码)按钮已经在init中分配:然后添加到子视图然后释放它,并且任何机会我在另一个类中设置按钮属性(我没有在dealloc中释放:)它会泄漏吗?登记/> 情况2:按钮已经在init中分配:然后添加到子视图然后释放它,并且任何机会我没有在另一个类中设置任何按钮属性(我没有使用该属性)(我在dealloc中释放它)然后就会崩溃。

那么,如果我想在init中分配按钮,我该怎么办?我也想设置属性?

@interface SomeClass : UIView {
UIButton *_button;
}
@property (nonatomic, retain)UIButton *button;

@implementation SomeClass
@synthesize button = _button;

- (id)init {
   _button = [[UIbutton alloc] initWithFrame:CGRectMake(0.0f,0.0f,100.0f,20.0f)];
   [[_button titleLabel] setFont:BUTTON_FONT];
   [_button setBackgroundImage:[[UIImage imageNamed:@"button_blue.png"] stretchableImageWithLeftCapWidth:20.0f topCapHeight:15.0f] forState:UIControlStateNormal];
   [_button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
   [_button setTitleShadowColor:[UIColor blackColor] forState:UIControlStateNormal];
   [[_button titleLabel] setShadowOffset:CGSizeMake(0.0f, 1.0f)];
   [_button addTarget:self action:@selector(buttonDidTapped:) forControlEvents:UIControlEventTouchUpInside];
   [self addSubView:_button];
   [_button release];
}

- (void)dealloc {
   //[self.button release]; // case 1
   [self.button release]; // case 2
   [super dealloc];
}
@end

6 个答案:

答案 0 :(得分:2)

  

那么,如果我想在init中分配按钮,我该怎么办?我也想设置属性?

以下是您的代码的外观:

@implementation SomeClass
@synthesize button = _button;

- (id)initWithFrame:(CGRect)frame {
   if ((self = [super initWithFrame:frame])) {
       UIButton *button = [[UIbutton alloc] initWithFrame:CGRectMake(0.0f,0.0f,100.0f,20.0f)];

       // Setup the button here...

       [self addSubView:button];
       self.button = button;
       [button release];
   }
   return self;
}

- (void)dealloc {
   [_button release];
   [super dealloc];
}
@end

我所做的改变:

  • initWithFrame:UIView的指定初始值设定项,因此这是您必须覆盖的init方法
  • 在设置课程之前,请务必检查以确保您的超类已成功初始化
  • 你必须在init语句结束时返回self。我不认为你的代码会编写为编写。
  • 您创建了一个属性,您应该使用它。使用temp变量为按钮进行所有设置,然后在完成设置后,使用属性accesssor设置变量并释放temp变量。
  • 因为您只使用该属性来获取/设置按钮,所以当需要dealloc时,您可以保证_button iVar有效或无效。无论哪种方式调用该变量的释放都可以。

答案 1 :(得分:1)

我不明白“将它用于只读”是什么意思。如声明的那样,该属性对于类本身和外部都是可读写的。但是问题可以合理地回答 - 一旦你的类保留了一些对象,它必须在它被解除分配时释放它


P.S。我认为您可以安全地删除私有变量的下划线前缀,它没有任何实际意义,并且可以让您编写更多代码。实际上,使用现代运行时,您甚至可以删除实例变量声明:

@interface Foo : NSObject {}
@property(assign) BOOL bar;
@end

@implementation Foo
@synthesize bar;
@end

答案 2 :(得分:1)

好的,第三次尝试:问题是你实际上是通过分配实例变量来设置属性。当您提供以下声明时,属性和实例变量紧密相关...

@synthesize button = _button;

...您说的是_button实例变量应该用于存储button属性的值。这意味着您的代码过度发布,因为您在init(+1)中分配按钮,释放init( - 1)中的按钮,然后再次在dealloc中释放( - 再次1)。

如果您尚未研究Cocoa Memory Management Guide,请执行此操作。即使你不打算阅读任何其他文件(这可能是遗憾的),用这个文件做一个例外,它会给你足够的回报。

答案 3 :(得分:0)

当然,你应该释放它,因为你已经使用了retain。

答案 4 :(得分:0)

-init方法中,您有一个平衡的retain / release来电。所以你不需要再次发布它。但通过这样做,你牺牲了_button所持有的价值的可靠性。如果在通道的某个位置按钮被从子视图中移除,则按钮的retainCount可能会达到零并且可以取消分配。然后_button保持的值是垃圾。因此,您不应在_button中发布-init,而应该在-dealloc中执行此操作。

现在,如果你在其他地方(在这个UIView对象之外)访问该属性,除非你将它保留在那里,否则你不需要再次释放它。

答案 5 :(得分:-2)

尝试将[self.button release];替换为[self.button removeFromSuperview];