我有点困惑。我正在继承UITableViewCell
来创建我自己的单元格设计。在-initWithStyle:
方法中,我设置了一些UILabel
,如下所示:
self.careerTitleLabel = [[UILabel alloc] init];
[self.contentView addSubview:careerTitleLabel];
[self.careerTitleLabel release];
然后定位标签我在-layoutSubviews
中这样做:
CGRect careerTitleLabelFrame = CGRectMake(10, 10, 280, 20);
self.careerTitleLabel.frame = careerTitleLabelFrame;
此代码实际上有效。它将我的标签定位在我希望它定位的位置。但我不明白的是 HOW 这是有效的。因为我只是修改了careerTitleLabel ivar的框架,而不是已经作为subView添加到contentView的careerTitleLabel。
我的假设是修改我添加到contentView的标签的框架,我必须使用-viewWithTag:
将其拉出来,然后修改该框架。现在我只是在修改班级的伊娃?
P.S与此问题无关的另一个悬念是为什么self.careerTitleLabel在释放后的retainCount为2? D.S
答案 0 :(得分:3)
addSubview:
不会复制您传递的视图,它会保留它。所以当你发布它时,它实际上并没有被释放。由于self.contentView
仍在使用它,因此它保持活着状态。这意味着你以后对self.careerTitleLabel的引用仍然可行,但我认为大多数人会认为它是不好的风格,理由是你应该继续拥有对你打算稍后发送的任何对象的引用,而不是从其他地方使用的所有权模式中归咎于知识。
retainCount
永远不会完全依赖。它也是不透明的addSubview:
将增加保留计数,除了它至少为1.这就是说,最可能的原因,如果你已宣布careerTitleLabel
为财产并拥有像这样的一行:
NSLog(@"%d", [self.careerTitleLabel retainCount]);
标准的吸气剂是:
return [[careerTitleLabel retain] autorelease];
因此,getter暂时增加了保留计数,其原因是getter的结果至少应该与autorelease池一样长 - 即使你从中获取它们的对象在那之前被解除分配。
答案 1 :(得分:1)
careerTitleLabel
是指向对象的指针。因此,当您执行addSubview: careerTitleLabel
时,您调用的代码会保留对careerTitleLabel
的引用。
稍后,当您在careerTitleLabel
中的layoutSubviews
上设置框架时,您正在更新同一个对象。
layoutSubviews
绝对是正确的选择。它在开始时自动调用,如果视图边界发生变化则再次调用。例如,如果设备的方向发生变化。
viewWithTag
是访问子视图的另一种方式。我个人认为维持ivar更清洁。不要忘记你可以使用IBOutlets使用Interface Builder来连接这些东西。
最后,您确实遇到了内存问题,这解释了保留计数。经常运行Analyze来解决这些问题,并使用Leaks进行配置文件,这是很好的。您甚至可以在构建设置中设置一个标记,以便在每次构建时始终运行Analyze。
无论如何这是问题所在:
self.careerTitleLabel = [[UILabel alloc] init];
如果.h文件中的属性设置为:
@property (nonatomic, retain)
那么你会在这里过度保留。您将保留两次,这将导致内存问题。
Apple指南建议您不要在init方法中调用这些setter。在那个阶段,行为可能是不可预测的,因为您可能正在通过自定义setWhatever方法,而您的对象尚未完成它的初始化。
更安全的是:
careerTitleLabel = [[UILabel alloc] init];
更好的是,在你的.h文件前缀中,这个成员变量为“m”。那你就有了
mCareerTitleLabel = [[UILabel alloc] init];
在你的合成中,使用:
synthesize careerTitleLabel = mCareerTitleLabel;
这意味着从您的代码的外部或内部,您可以访问:
self.careerTitleLabel
或
myObjectName.careerTitleLabel
我希望这有帮助!这要涵盖很多!