2012-05-27 51 views
2

我有一个基本的UITableView,有四个部分。我用Switch语句控制每个部分的内容。IOS:停止单元在UITableView中被错误地重用

我以编程方式创建一个按钮,它应该出现在前三个部分的行中,但不应出现在第四个中。但是,该按钮在第四部分的行中随机出现。

我认为这是因为一个单元格正在被重用,但是当我用Switch语句创建每个部分的行时,我看不到这是如何发生的。任何想法赞赏。

我使用的配置,以便自定义单元格:`

static NSString *CustomCellIdentifier = @"DashboardCell"; 

DashboardCell *cell = (DashboardCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier]; 

if (cell == nil) { NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"DashboardCell" 
                   owner:self options:nil]; 
    for (id oneObject in nib) if ([oneObject isKindOfClass:[DashboardCell class]]) 
     cell = (DashboardCell *)oneObject; 
} 

// Configure the cell.` 

代码来创建这个按钮是:`

 button = [UIButton buttonWithType:UIButtonTypeCustom]; 
     button.frame = CGRectMake(200, 11, 50, 50);   
     UIImage *iConnect = [UIImage imageNamed:@"connect.png"]; 
     [button setImage:iConnect forState:UIControlStateNormal]; 
     [button addTarget:self action:@selector(buttonSelected:) forControlEvents:UIControlEventTouchUpInside]; 
     [cell addSubview:button];` 

回答

11

你需要一个不同的重用标识符每种类型的内容。所以在这里你有两种类型的内容 - 单元格有UIButton,单元格没有。

使用tableView:cellForRowAtIndexPath:方法的indexPath来选择@“CellWithButton”或@“CellWithoutButton”的重用标识符。

代码中实际发生的事情是,所有单元都被赋予相同的重用标识符,这意味着它们都被放入同一个对象池中。这意味着当您使用[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];时,您正在从此池中检索一个单元格(可能包含没有UIButton的单元格以及有此单元格的单元格)。因此,出列方法可以随机返回一个已经添加了UIButton的单元格。如果您使用两个重用标识符,则UITableView将设置两个对象池,并将正确存放和检索每个对象池中的相应单元格。

或者您可以使用一个重复使用池,并在每次使用出列方法检索一个UIButton时检查单元格。

+0

感谢Barjavel。我创建了两种细胞类型。奇迹般有效。 – Jeremy

1

您可以使用两种不同的细胞识别取决于部分。否则,您需要查看该按钮是否存在于从dequeueReusableCellWithIdentifier:返回的单元格中,并在必要时添加一个或删除现有的按钮。

+0

我会补充说,你可能只是添加新的控制顶部的旧按钮,所以虽然你认为它的工作它不是。这只是一次你没有画出那个按钮的例子。 – madmik3

+0

@ madmik3 - 你可能是对的,虽然从按钮创建代码在什么条件下执行的问题不清楚。也许它直接跟随或者额外缩进有意义。 [耸肩] :) –

7

在您的DashboardCell中,创建一个属性@property (nonatomic, assign) BOOL buttonEnabled。然后在你的awakeFromNib,总是创建按钮并设置button.hidden = YES。重写你的setter方法

- (void)setButtonEnabled:(BOOL)enabled { 
    buttonEnabled = enabled; 
    button.hidden = !enabled; 
} 

最后覆盖prepareForReuse

- (void)prepareForReuse { 
    [super prepareForReuse]; 
    self.buttonEnabled = NO; 
} 

现在你可以enbale /禁用方法的cellForRowAtIndexPath你的配置部分

+0

谢谢@iTukker! – Lito

+0

这应该是被接受的答案,通过使用非常容易使用 - (void)prepareForReuse –

0

如果您打算重用这些单元格,并且在显示或隐藏每个单元格的按钮后面有一些简单的逻辑,我建议的第一件事是您在Interface Builder中创建按钮并将其作为出口连接到您的UITableViewDelegate 。

我会再创建,你可以在任何时候运行单元的设置方法,突破任意数量的没有它有时它:

-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath 
{ 
    static NSString *CustomCellIdentifier = @"DashboardCell"; 

    DashboardCell *cell = (DashboardCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier]; 

    if (cell == nil) { NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"DashboardCell" 
                   owner:self options:nil]; 
     for (id oneObject in nib) if ([oneObject isKindOfClass:[DashboardCell class]]) 
      cell = (DashboardCell *)oneObject; 
    } 

    // Configure the cell. 
    [cell setupWithSomeConfigOptions:someConfigOptions] 

    return cell; 
} 

而且在你的子类中,你将有方法-(void)setupWithSomeOptions:(SomeOptions)someOptions,这将是沿线的东西:

-(void)setupWithSomeOptions:(SomeOptions)someOptions 
{ 
    // some setup code 

    self.myButtonOutlet.hidden = someOptions.somePropertyToCheckIfButtonShouldBeHidden; 

    // some more setup code 
}