假设我的视图控制器中有一个属性,定义如下:
@property (nonatomic, retain) UIImageView *checkmarkOffAccessoryView;
我@synthesize
在实施中,release
在-dealloc
中,并在-viewDidLoad
中初始化,如下所示:
self.checkmarkOffAccessoryView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]] autorelease];
到目前为止一切顺利。
当我在我的表视图中使用它作为多个单元格的附件视图时,会发生两件事:
应用程序不会崩溃,因为我可以说,用户界面根本没有响应。这都在模拟器和设备上。
以下是我如何将初始化属性与我的单元格一起使用:
- (UITableViewCell *) tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// initialize or dequeue cell...
if (condition)
cell.accessoryView = self.checkmarkOffAccessoryView;
else
cell.accessoryView = nil;
}
使用上述代码,只有一个单元格显示附件视图,并且UI冻结。
如果我直接在委托方法中初始化UIImageView
实例,我会得到所有满足条件的单元格,显示附件视图,并且我没有遇到UI冻结:
- (UITableViewCell *) tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// initialize or dequeue cell...
if (condition)
cell.accessoryView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]] autorelease];
else
cell.accessoryView = nil;
}
我的目标是初始化尽可能少的对象并重用一个UIImageView
。我很好奇为什么第一块代码是有问题的,我可以做些什么来解决这个问题。
似乎单元格的accessoryView
属性应该只增加retain
self.checkmarkOffAccessoryView
的{{1}}计数,但看起来我错过了一些细节。
我忽略了什么?谢谢你的建议。
修改
我认为:
self.checkmarkOffAccessoryView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]] autorelease];
与:
相同UIImageView *uncheckedView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]];
self.checkmarkOffAccessoryView = uncheckedView;
[uncheckedView release];
无论哪种方式,我都会遇到相同的冻结症状。
答案 0 :(得分:9)
您无法多次添加同一视图。 UI处理程序将疯狂。为了确保这一点,我试着按照你上面所说的做,我也遇到了同样的问题。 UI冻结,图像仅出现在其中一个单元格中。
你可以做的最好的事情是将你的图像存储为分配的UIImage,并有一个帮助函数,每个单元格返回一个新的UIImageView。
使用您当前的方法(没有存储的UIImage),您可能会这样做:
-(UIImageView *) makeCheckmarkOffAccessoryView
{
return [[[UIImageView alloc] initWithImage:
[UIImage imageNamed:@"checkmarkOff.png"]] autorelease];
}
然后再做
cell.accessoryView = [self makeCheckmarkOffAccessoryView];
您可能知道,另一方面,UIImages可能会被使用多次。 UIImageView不占用大量空间,因此您可以轻松拥有一堆而不用担心。
要扩展一个地方的交易,想象你同时在两个地方添加一个UIView。
[ob removeFromSuperview]会为此对象做些什么?它会从两个地方删除视图吗?只从他们中的一个?请求[ob superview]时会返回哪个值?很明显,用户界面并不是为了处理您所要求的内容。
答案 1 :(得分:0)
尝试在初始化程序中没有自动释放。我怀疑你过度释放了。
顺便说一下,你的控制台在冻结时可能会显示BAD_ACCESS错误。如果你打开NSZombieEnabled,我猜你会看到它正在调用一个解除分配的UIImage。
答案 2 :(得分:0)
也许这会有所帮助
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"ShoppingListCell";
HSShoppingListCell *cell = (HSShoppingListCell *)[aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:@"ShoppingListCell"
owner:self
options:nil];
cell = shoppingListCell;
}
ShoppingListItem *theItem = nil;
theItem = [self.fetchedResultsController objectAtIndexPath:indexPath];
UIImage *selected = [UIImage imageNamed:@"listBullet_checked.png"];
UIImage *notSelected = [UIImage imageNamed:@"listBullet.png"];
cell.imageView.image = ([theItem.checkedOff boolValue] ? selected : notSelected);
cell.shoppingListLabel.text = theItem.productName;
[cell.shoppingListLabel setFont:[UIFont fontWithName:@"Marker Felt" size:26.0]];
return cell;
}
- (void)toggleCellImage:(NSIndexPath *)indexPath
{
ShoppingListItem *item = [self.fetchedResultsController objectAtIndexPath:indexPath];
item.checkedOff = ([item.checkedOff boolValue] ? [NSNumber numberWithBool:NO] : [NSNumber numberWithBool:YES]);
[HSCoreDataUtilities saveContext:item.managedObjectContext];
[self.tableView reloadData];
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self toggleCellImage:indexPath];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
答案 3 :(得分:0)
将你的情况减少到最基本要求(我建议在UIView
周围放置两个'瘦'UIImageView
个对象......)我发现这很可能是不可能的。< / p>
在IB中创建2个空UIView
个对象,将它们连接到bareView1
和bareView2
。然后
UIImageView *imageView = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:@"test.png"]];
[bareView1 addSubview:imageView]; // it shows either here ...
[bareView2 addSubview:imageView]; // ... or here
你永远不能在这样的情况下多次获得图像。根据经验,我认为 not 继承自UIView
的第一个对象可以多次使用,即UIImage
。与Kalle所说的一样,UIView
在视图层次结构中只能有一个父级。
延迟第二个addSubview
只会使UIImageView
从bareView1
跳转到bareView2
。
冻结可能是因为事件处理混淆了:附件可以是交互式的,如果它们是同一个对象,你怎么知道哪一个被轻敲?所以代码假设对象是唯一的,并且你设法违反了这个假设。