【问题标题】:UIButton reused in UITableViewCell when scrolling滚动时在 UITableViewCell 中重用的 UIButton
【发布时间】:2015-08-06 18:03:27
【问题描述】:

在我的 UITableView 中,有标题单元格和标准单元格。每个标准单元格都添加了一个复选框(UIButton),使用以下两种方法。

调用下面的方法来创建每个UITableViewCell

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

static NSString *tableIdentifier = @"activityIdentifier";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableIdentifier];

// HEADER ROWS
if (indexPath.row == 0 || indexPath.row == 5 || indexPath.row == 10 || indexPath.row == 15 || indexPath.row == 20 || indexPath.row == 25 || indexPath.row == 30) {

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier];
        NSLog(@"Yeaa!");
    }

    cell.textLabel.text = [activityArray objectAtIndex:indexPath.row];
    cell.textLabel.textColor = [UIColor blackColor];
    cell.textLabel.font = [UIFont fontWithName:@"Aliquam" size:13.0f];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.backgroundColor = [UIColor whiteColor];
    static int a = 20.0f;
    tableView.rowHeight = a;

} else {
    // STANDARD ROWS
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier];
        NSLog(@"Standard cell is nil");

    }

    cell.textLabel.text = [activityArray objectAtIndex:indexPath.row];
    cell.backgroundColor = [UIColor clearColor];
    cell.textLabel.textColor = [UIColor whiteColor];
    cell.textLabel.font = [UIFont fontWithName:@"Aliquam" size:20.0f];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    static int b = 44.0f;
    tableView.rowHeight = b;
}

// CREATE CHECK BOXES IN STANDARD ROWS
if (indexPath.row == 1) {
    [self createRoleCheckbox:actMondayMorning];
    [cell addSubview:actMondayMorning];
} else if (indexPath.row == 2) {
    [self createRoleCheckbox:actMondayAfternoon];
    [cell addSubview:actMondayAfternoon];
} else if (indexPath.row == 3) {
    [self createRoleCheckbox:actMondayEvening];
    [cell addSubview:actMondayEvening];
} else if (indexPath.row == 4) {
    [self createRoleCheckbox:actMondayNight];
    [cell addSubview:actMondayNight];
} else if (indexPath.row == 6) {
    [self createRoleCheckbox:actTuesdayMorning];
    [cell addSubview:actTuesdayMorning];
} else if (indexPath.row == 7) {
    [self createRoleCheckbox:actTuesdayAfternoon];
    [cell addSubview:actTuesdayAfternoon];
} else if (indexPath.row == 8) {
    [self createRoleCheckbox:actTuesdayEvening];
    [cell addSubview:actTuesdayEvening];
} else if (indexPath.row == 9) {
    [self createRoleCheckbox:actTuesdayNight];
    [cell addSubview:actTuesdayNight];
} else if (indexPath.row == 11) {
    [self createRoleCheckbox:actWednesdayMorning];
    [cell addSubview:actWednesdayMorning];
} else if (indexPath.row == 12) {
    [self createRoleCheckbox:actWednesdayAfternoon];
    [cell addSubview:actWednesdayAfternoon];
} else if (indexPath.row == 13) {
    [self createRoleCheckbox:actWednesdayEvening];
    [cell addSubview:actWednesdayEvening];
} else if (indexPath.row == 14) {
    [self createRoleCheckbox:actWednesdayNight];
    [cell addSubview:actWednesdayNight];
} else if (indexPath.row == 16) {
    [self createRoleCheckbox:actThursdayMorning];
    [cell addSubview:actThursdayMorning];
} else if (indexPath.row == 17) {
    [self createRoleCheckbox:actThursdayAfternoon];
    [cell addSubview:actThursdayAfternoon];
} else if (indexPath.row == 18) {
    [self createRoleCheckbox:actThursdayEvening];
    [cell addSubview:actThursdayEvening];
} else if (indexPath.row == 19) {
    [self createRoleCheckbox:actThursdayNight];
    [cell addSubview:actThursdayNight];
} else if (indexPath.row == 21) {
    [self createRoleCheckbox:actFridayMorning];
    [cell addSubview:actFridayMorning];
} else if (indexPath.row == 22) {
    [self createRoleCheckbox:actFridayAfternoon];
    [cell addSubview:actFridayAfternoon];
} else if (indexPath.row == 23) {
    [self createRoleCheckbox:actFridayEvening];
    [cell addSubview:actFridayEvening];
} else if (indexPath.row == 24) {
    [self createRoleCheckbox:actFridayNight];
    [cell addSubview:actFridayNight];
} else if (indexPath.row == 26) {
    [self createRoleCheckbox:actSaturdayMorning];
    [cell addSubview:actSaturdayMorning];
} else if (indexPath.row == 27) {
    [self createRoleCheckbox:actSaturdayAfternoon];
    [cell addSubview:actSaturdayAfternoon];
} else if (indexPath.row == 28) {
    [self createRoleCheckbox:actSaturdayEvening];
    [cell addSubview:actSaturdayEvening];
} else if (indexPath.row == 29) {
    [self createRoleCheckbox:actSaturdayNight];
    [cell addSubview:actSaturdayNight];
} else if (indexPath.row == 31) {
    [self createRoleCheckbox:actSundayMorning];
    [cell addSubview:actSundayMorning];
} else if (indexPath.row == 32) {
    [self createRoleCheckbox:actSundayAfternoon];
    [cell addSubview:actSundayAfternoon];
} else if (indexPath.row == 33) {
    [self createRoleCheckbox:actSundayEvening];
    [cell addSubview:actSundayEvening];
} else if (indexPath.row == 34) {
    [self createRoleCheckbox:actSundayNight];
    [cell addSubview:actSundayNight];
}

return cell;
}

调用下面的方法来创建复选框(UIButton):

- (void) createRoleCheckbox:(UIButton *)passedButton {

passedButton.frame = CGRectMake(screenWidth-checkboxDiameter-(checkboxInset/2), (checkboxInset/2), checkboxDiameter, checkboxDiameter);

[passedButton setImage:checkboxImageUnselected forState:UIControlStateNormal];
[passedButton setImage:checkboxImageSelected forState:UIControlStateSelected];

if (passedButton == actMondayMorning)
    [passedButton addTarget:self action:@selector(actMondayMorningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actMondayAfternoon)
    [passedButton addTarget:self action:@selector(actMondayAfternoonPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actMondayEvening)
    [passedButton addTarget:self action:@selector(actMondayEveningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actMondayNight)
    [passedButton addTarget:self action:@selector(actMondayNightPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actTuesdayMorning)
    [passedButton addTarget:self action:@selector(actTuesdayMorningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actTuesdayAfternoon)
    [passedButton addTarget:self action:@selector(actTuesdayAfternoonPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actTuesdayEvening)
    [passedButton addTarget:self action:@selector(actTuesdayEveningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actTuesdayNight)
    [passedButton addTarget:self action:@selector(actTuesdayNightPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actWednesdayMorning)
    [passedButton addTarget:self action:@selector(actWednesdayMorningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actWednesdayAfternoon)
    [passedButton addTarget:self action:@selector(actWednesdayAfternoonPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actWednesdayEvening)
    [passedButton addTarget:self action:@selector(actWednesdayEveningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actWednesdayNight)
    [passedButton addTarget:self action:@selector(actWednesdayNightPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actThursdayMorning)
    [passedButton addTarget:self action:@selector(actThursdayMorningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actThursdayAfternoon)
    [passedButton addTarget:self action:@selector(actThursdayAfternoonPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actThursdayEvening)
    [passedButton addTarget:self action:@selector(actThursdayEveningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actThursdayNight)
    [passedButton addTarget:self action:@selector(actThursdayNightPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actFridayMorning)
    [passedButton addTarget:self action:@selector(actFridayMorningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actFridayAfternoon)
    [passedButton addTarget:self action:@selector(actFridayAfternoonPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actFridayEvening)
    [passedButton addTarget:self action:@selector(actFridayEveningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actFridayNight)
    [passedButton addTarget:self action:@selector(actFridayNightPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actSaturdayMorning)
    [passedButton addTarget:self action:@selector(actSaturdayMorningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actSaturdayAfternoon)
    [passedButton addTarget:self action:@selector(actSaturdayAfternoonPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actSaturdayEvening)
    [passedButton addTarget:self action:@selector(actSaturdayEveningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actSaturdayNight)
    [passedButton addTarget:self action:@selector(actSaturdayNightPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actSundayMorning)
    [passedButton addTarget:self action:@selector(actSundayMorningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actSundayAfternoon)
    [passedButton addTarget:self action:@selector(actSundayAfternoonPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actSundayEvening)
    [passedButton addTarget:self action:@selector(actSundayEveningPressed) forControlEvents:UIControlEventTouchUpInside];
else if (passedButton == actSundayNight)
    [passedButton addTarget:self action:@selector(actSundayNightPressed) forControlEvents:UIControlEventTouchUpInside];

}

此代码正确地在每一行中创建复选框。

但是,当我滚动浏览我的应用程序时,UIButtons 重复,随机出现在标题单元格中。

此外,如果我单击一个按钮,使其处于选中状态,当我滚动时,其他按钮也会随机处于选中状态,即使我没有按下它们。

简而言之,UIButtons 正在被重复使用。我怎么能不发生这种情况?

感谢所有帮助。

【问题讨论】:

    标签: ios objective-c uitableview uibutton


    【解决方案1】:

    首先,将按钮添加到单元格的 contentView 中,然后清除 contentView,在添加按钮之前删除所有内容。让我知道这是否有效。

    【讨论】:

    • 您是否介意解释一下这是如何完成的(最好是一些基本的示例代码),以及为什么它会起作用?根据您的描述,简单地从 contentView(或 anything)中添加并立即删除 UIButton 肯定不会产生净效果吗?
    【解决方案2】:

    你需要重构你的代码。

    您应该为您创建的每种结构不同类型的单元格设置不同的标识符。

    如果您的标题单元格的元素与您的“标准”单元格不同,请让您的 cellForRowAtIndexPath 方法首先确定这是否是标题行。如果是标题行,则使用标题单元格的 ID 调用 dequeueReusableCellWithIdentifier。如果没有,请使用“标准”单元格的标识符调用它。

    这样,只有在正确类型之一可用时,您才会得到一个回收的单元格,而当您想要一个“标准”单元格时,您永远不会得到一个标题单元格。

    【讨论】:

    • 这会阻止 UIButtons 出现在标题中,谢谢。然而,不幸的是,我在 TableView 顶部选择一个单元格、向下滚动以及让一个随机单元格也处于选定状态的主要问题并没有改变。我可以上下滚动,选中状态的 UIButton 会随机切换单元格。
    【解决方案3】:

    首先,我强烈建议不要创建“标题”单元格,而是使用部分,您不需要为特定的 indexPath 行设置条件。

    另一方面,不清楚如何创建按钮,但据我所知,每次单元格显示在屏幕上时,您只是添加一个按钮,也不清楚 indexPath.rows 如何传递给 createRoleCheckbox 方法,因为它只接受一个 UIButton 作为参数。

    无论如何,我认为根据行创建按钮不是一个好主意,我会创建一个按钮,并根据行更改选择器(以及我想的标题),例如这个:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
        static NSString *tableIdentifier = @"activityIdentifier";
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableIdentifier];
    
        // Since you switched to section they are all standard rows now
        if (cell == nil) {
                cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier];
                NSLog(@"Standard cell is nil");
    
        }
    
        UIButton *cellButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        cellButton.frame = CGRectMake(0.0, 0.0, 150.0, 30.0);
        [cell addSubview:cellButton];
    
        cell.textLabel.text = [activityArray objectAtIndex:indexPath.row];
        cell.backgroundColor = [UIColor clearColor];
        cell.textLabel.textColor = [UIColor whiteColor];
        cell.textLabel.font = [UIFont fontWithName:@"Aliquam" size:20.0f];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        static int b = 44.0f;
        tableView.rowHeight = b;
    
    
        if (indexPath.row == 1) {
             [cellButton addTarget:self action:@selector(appropiateMethod) forControlEvents:UIControlEventTouchUpInside];
             [cellButton setTitle:@"Appropiate Title" forState:UIControlStateNormal];
        } else if (indexPath.row == 2) {
             [cellButton addTarget:self action:@selector(appropiateMethod) forControlEvents:UIControlEventTouchUpInside];
             [cellButton setTitle:@"Appropiate Title" forState:UIControlStateNormal];
        } else if (indexPath.row == 3) {
             [cellButton addTarget:self action:@selector(appropiateMethod) forControlEvents:UIControlEventTouchUpInside];
             [cellButton setTitle:@"Appropiate Title" forState:UIControlStateNormal];
        } ...
    
        return cell;
    }
    

    这种方法都会使 createRoleCheckbox 方法完全没有必要。

    希望这会有所帮助!

    【讨论】:

    • 这会阻止 UIButtons 出现在标题行中,但遗憾的是仍然不能解决重复错误。如果我在 TableView 顶部选择一个单元格,然后滚动到底部,一个随机选择的 UIButton 将处于选中状态。然后我可以上下滚动,所选按钮将移动位置,尽管我实际选择的按钮仍然保留。
    【解决方案4】:

    我已经解决了我的问题。这有点像贫民窟的解决方案,我相信纯粹主义者可能会对此提出异议(老实说,它可能会以某种方式导致内存问题,但这对我的应用程序来说不应该是问题,因为视图控制器只是短暂打开)。

    首先,我将UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableIdentifier]; 替换为UITableViewCell *cell

    然后我将cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier]; 替换为cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];。我的代码在技术上与此略有不同,但这是我所做工作的本质。我想我会停止代码重用按钮,好吧,停止它重用按钮。希望这对将来的某人有所帮助,并且不会引起比它解决的更多的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 2012-10-07
      • 2016-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多