ios - UITableView 单元格被发送 setSelected :NO during layoutView

标签 ios objective-c uitableview autolayout

我看到 viewDidLayoutSubviews 和 UITableViewCells 发生了一些奇怪的事情。

我在一个页面上有 2 个表格,它们都调整了大小,因此它们不会滚动(所有元素都可见)。我像这样处理 viewDidLayoutSubviews 中的大小调整:

- (void)viewDidLayoutSubviews {
    self.orderItemTableViewHeightConstraint.constant = self.orderItemTableView.contentSize.height - [self tableView:self.orderItemTableView heightForHeaderInSection:0];
    self.shippingOptionTableViewHeightConstraint.constant = self.shippingMethodTableView.contentSize.height;

    [self.view layoutIfNeeded];

    self.scrollViewContainerViewHeightConstraint.constant = self.shippingMethodTableView.$bottom;

    [self.view layoutIfNeeded];
}

这按预期工作。

但是,当构建 shippingOptionTableView 时,它有 3 个单元格(对于本例),每个单元格都有一个模型,该模型在单元格中提供标签和一个选择标记,如下所示:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (tableView == self.shippingMethodTableView) {
        DLShippingOptionTableCell *cell = [tableView dequeueReusableCellWithIdentifier:SHIPPING_OPTION_CELL_IDENTIFIER];

        if (cell == nil) {
            NSString *nibName = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) ? @"DLShippingOptionTableCell~iphone" : @"DLShippingOptionTableCell";

            NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:nibName owner:nil options:nil];

            for (id currentObject in topLevelObjects) {
                if ([currentObject isKindOfClass:[DLShippingOptionTableCell class]]) {
                    cell = (DLShippingOptionTableCell *)currentObject;
                    [cell setupCell];
                    break;
                }
            }
        }

        cell.model = [self.model.shippingOptionArray objectAtIndex:indexPath.row];

        return cell;
    }
    else {
        ...
    }
}

模型在表格单元格中设置,这会导致视觉状态更新:

- (void)setModel:(DLShippingOption *)model {
    _model = model;

    NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
    [currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];

    NSString *numberAsString = [currencyFormatter stringFromNumber:[NSNumber numberWithFloat:(model.priceInPennies / 100.0f)]];

    self.shippingLabel.text = [NSString stringWithFormat:@"%@ (%@)", model.optionName, numberAsString];

    [self toggleSelectedState:model.isSelected];
}

- (void)toggleSelectedState:(BOOL)isSelected {
    [self setSelected:isSelected];

    self.radioButtonImageView.image = isSelected ? [UIImage imageNamed: @"radio_button_selected.jpg"] : [UIImage imageNamed: @"radio_button_unselected.jpg"];
}

这就是问题所在……表格单元格在布局过程中重复发送 setSelected:NO。因此,即使我的模型设置为选中,并且我更新了单选按钮图形(我通常会在 setModel: 中这样做),它也会被覆盖并更改为 false。

我必须将这个 hack 放在适当的位置以使其工作(基本上是将这段代码添加到 ViewController 中的 cellForRowAtIndexPath,就在设置单元格的模型之后:

if (cell.model.isSelected) {
    [self.shippingMethodTableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}

我这个咬...所以问题是,为什么表格单元格在布局期间一遍又一遍地发送 setSelected:NO,有没有更好的方法来克服这个问题?

最佳答案

尝试使用 prepareForReuse 方法,看看是否有帮助。查看此处的文档也会很有帮助:

https://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html

如果 UITableViewCell 对象是可重用的(即,它具有重用标识符),则在从 UITableView 方法 dequeueReusableCellWithIdentifier: 返回该对象之前调用此方法。 出于性能原因,您应该只重置与内容无关的单元格属性,例如 Alpha、编辑和选择状态。 tableView:cellForRowAtIndexPath: 中的 TableView 委托(delegate)在重用单元格时应始终重置所有内容。如果单元对象没有关联的重用标识符,则不会调用此方法。如果重写此方法,则必须确保调用父类(super class)实现。

另请注意,您应该仅将此方法用于与文档中指出的内容相关的内容。内容相关的事情应该始终在 tableView:cellForRowAtIndexPath: 方法中完成

关于ios - UITableView 单元格被发送 setSelected :NO during layoutView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24497419/

相关文章:

ios - 真正的 iPhone XR 屏幕分辨率与 swift 给出的屏幕分辨率不同?

iphone - 更快的 if 语句

ios - 调整消息传递应用程序的 View

json - Swift - JSON 解码返回空数组

ios - 类 UITableViewCell 没有名为 Storyboard的成员

ios - 如何在Core Plot CPT ScatterPlot中绘制不同的线条颜色

ios - UIButton 按下不会调用函数

ios - 为什么 UIButton 消耗触摸而不是 UIControl

objective-c - 为什么要释放此对象?

ios - Swift:在 TableView Prototype Cell 中获取 Label 以显示多行(自动换行)