IOS:停止在UITableView中错误地重用单元格

时间:2012-05-27 15:49:03

标签: ios uitableview uibutton switch-statement cells

我有一个基本的UITableView有四个部分。我用Switch语句控制每个部分的内容。

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

我认为这是因为一个单元正在被重用,但是当我使用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];`

4 个答案:

答案 0 :(得分:11)

您需要为每种类型的内容使用不同的重用标识符。所以这里有两种类型的内容 - 具有UIButton的单元格和不具有indexPath的单元格。

使用tableView:cellForRowAtIndexPath:方法的[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];选择@“CellWithButton”或@“CellWithoutButton”的重用标识符。

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

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

答案 1 :(得分: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;
}

现在你可以在方法cellForRowAtIndexPath的配置部分中进行enbale / disable

答案 2 :(得分:1)

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

答案 3 :(得分: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
}