Iphone 我应该在哪里调用[对象释放]?
我对一些UITextField进行了子类化,并添加了一些自定义属性 在UITableViewController中,我在ViewDiDLoad中初始化它们,在cellForRowAtIndexPath中,我使用[cell.contentView addSubview:customTextField]将它们添加到单元格中 每个单元格都有一个不同的customTextField,因为它们都非常不同 我应该在哪里调用[customTextField release] 在我将它们添加到单元视图之后 例如,如果我调用[self.tableView reloadData],我的customTextField将被再次添加到单元格中,那么我是否应该改变这样做的方法 谢谢你的介绍 问候,Iphone 我应该在哪里调用[对象释放]?,iphone,memory-management,Iphone,Memory Management,我对一些UITextField进行了子类化,并添加了一些自定义属性 在UITableViewController中,我在ViewDiDLoad中初始化它们,在cellForRowAtIndexPath中,我使用[cell.contentView addSubview:customTextField]将它们添加到单元格中 每个单元格都有一个不同的customTextField,因为它们都非常不同 我应该在哪里调用[customTextField release] 在我将它们添加到单元视图之后 例如
r、 我总是在使用addSubView将控件添加到视图后直接释放控件。当我使用表时,我也在CellForRowatineXpath方法中初始化它们
因此,对象在最短的时间内保持活动状态。当您对对象不再感兴趣时,您可以
释放该对象。这有很多原因;这可能是因为您已经完成了对象,或者已经将对象生存期的控制权传递给了另一个对象。这可能是因为您将要用新实例替换对象,也可能是因为您(所有者对象)即将死亡
最后一个似乎与你的情况有关。您可以在viewDidLoad
中创建这些对象,并反复使用它们(即将它们添加到单元格),直到对象不再运行为止。在这种情况下,正如您在viewDidLoad
中创建它们一样,您可以在viewDidUnload
中释放它们
编辑:我真的应该提到自动释放
,但这与本例无关。内存管理最好用“所有者”的概念来处理——创建(或保留)某个东西的人应该负责删除它(或者用ObjC的说法是release
ing)autorelease
处理某些情况,在这些情况下,您需要将一个对象交给一个以前自己拥有它的备用所有者(通常通过返回方法)。如果您是创建者,您不能在将其返回给新所有者之前发布它,因为它将在新所有者有机会对其感兴趣之前被删除。然而,你不能只是不发布它;它会漏的。因此,系统提供了一个庞大的对象列表,它将在将来的某个时候代表您发布这些对象。您将您的release
职责传递给此列表,然后将对象返回给新所有者。此列表(自动释放池)确保您的释放将在某个时刻发生,但让新所有者有机会在对象被释放之前将其声明为自己的对象
在您的情况下,您显然有兴趣在视图控制器的生命周期内拥有这些对象—您需要随时能够将它们添加到视图单元以响应表数据重新加载。只有当视图控制器死亡时,才可以使用它们,因此viewDidUnload
(或者可能dealloc
)是释放它们的唯一合理位置。处理对象所有权的最安全方法是在初始化后直接自动释放视图:
FooTextField* textField = [[[FooTextField alloc] init] autorelease];
[myCell.contentView addSubview:textField];
将文本字段添加到superview(UITableViewCell
的contentView)会保留它。这样,您就不必关心以后是否发布视图
在iPhone开发者社区中,似乎存在着对自动释放的不满。在我看来,这种怨恨是没有根据的。如果对象的寿命比当前通过运行循环的时间长,则自动释放对象只会给程序增加很少的开销。您不应该在cellForRowAtIndexPath中添加子视图!当每次显示单元时添加子视图时,这将减慢视图的速度。为此,请尝试使用自定义UITableViewCell类
这是UITableView定制的完美解决方案
工作正常Obj-C中的每个对象都有一个引用计数器(重新计数),当该计数器变为0时,对象被释放。当您分配和初始化一个对象时,引用计数被设置为1-但是您可以保留它任意次数
UITextField *textField = [[UITextField alloc] init]; // Reference counter = 1
[textField retain]; // Reference counter = 2
[textField retain]; // Reference counter = 3
retain的反面是release,它从参考计数器中减去
...
[textField release]; // Reference counter = 2
[textField release]; // Reference counter = 1
您可以随时获取对象的参考计数器
printf("Retain count: %i", [textField retainCount]);
UIView
的方法addSubview
确实retain
您传入的子视图,当它完成时,它会释放它。如果以后需要在另一个作用域中使用UITextField
(当UIView
完成并已发布时)-将其添加到超级视图后,不应发布它。大多数情况下,您实际上不需要保留引用,因此您应该在将其添加到超级视图后释放它。如果你没有-你可以在你的范围内用dealloc方法发布它。亚当·赖特很好地解释了这个理论,但让我给你一些实践。你对这个问题想得太多了,这几乎总是导致错误。有一个简单的解决方案几乎每次都能解决这个问题:使用访问器保留所有IVAR;不要保留非IVAR
.h
@interface ... {
UITextField *_customTextField;
}
.m
@property (nonatomic, readwrite, retain) UITextField *customTextField;
...
@synthesize customTextField=_customTextField;
-(void)viewDiDLoad {
self.customTextField = [[[UITextField alloc] init....] autorelease];
}
...
- (void)dealloc {
// I do not recommend accessors in dealloc; but everywhere else I do
[_customTextField release]; _customTextField = nil;
}
永远不要直接访问IVAR,除非是在dealloc
中(即使这样也是有争议的,有些人建议self.customTextField=nil;
在dealloc
中;两种方式都有争议)。但不要直接分配IVAR。如果遵循此规则,您会发现大部分内存问题都会消失。请查看UITableView-dequeueReusableCellWithIdentifier:和-initWithStyle:reuseIdentifier:
在-tableView:cellforrowatinexpath:中,使用-dequeueReusableCellWithIdentifier:并检查结果是否为零。如果是,则使用-initWithStyle:reuseIdentifier:实例化一个新单元格
硒