重新加载后UITableView重置UITableViewCell

时间:2015-09-13 19:27:04

标签: ios swift uitableview

首先,我是如何使用UIPicker创建可扩展单元格的。以防万一与问题相关。

通过此代码在UITableView中创建

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var identifyer = ""
    switch(indexPath.row){
  //other cells
    case 1:
        //Kategoria
        identifyer = "category"
        categoryCell = tableView.dequeueReusableCellWithIdentifier(identifyer) as? CategoryTableViewCell
        categoryCell.pickerView.delegate = self
        categoryCell.pickerView.dataSource = self
        return categoryCell
  //other cells
}

然后我必须认识到它是否被触及

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    if (indexPath.row == 1){
        isCategoryCellSelected = true
        tableView.reloadRowsAtIndexPaths([categoryIndexPath()], withRowAnimation: UITableViewRowAnimation.Automatic)
    }
}

这就是我在UILabel

中替换文字的方式
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    categoryCell.categoryNameLabel.text = categories[row]
}

当tableView刷新单元格

时最终
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    switch(indexPath.row){
    case 1:
        if (isCategoryCellSelected){
            return CategoryTableViewCell.expandedHeight
        } else {
            return CategoryTableViewCell.defaultHeight
        }
     //other heights
    }
}

Defalut细胞看起来

[defalut]

扩展的单元格外观

[expanded]

问题

因此,当我选择拾取器中的项目时,上面的标签应该更改它的文本并且正在发生。但是,当此单元格缩小到默认高度时,替换效果就消失了。我必须向下滚动才能看到只有这样我才能在标签中看到更改的文字。

我假设UITableView缓存此单元格,当单元格重新加载时,它将采用此缓存版本。我只是在猜测。这是我的想法吗?我怎样才能改变这种不必要的行为?

正如@the_critic所指出的那样,我在vars中保存细胞是完全错误的。同时每次选择行重新创建categoryCell都不是正确的方法。我最终以他创造细胞的方式,但我的方式是为细胞设定价值。

所以它看起来像是被谴责的:

创建单元格

categoryIdentifier为private let String

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell: UITableViewCell
    switch(indexPath.row){
// other cells
   case 1:
        //Kategoria
        print("recreate, selected category \(selectedCategory)")
        let categoryCell = tableView.dequeueReusableCellWithIdentifier(categoryIdentifier) as! CategoryTableViewCell
        categoryCell.pickerView.delegate = self
        categoryCell.pickerView.dataSource = self
        updateSelectedCategoryIfNeeded(categoryCell)
        cell = categoryCell

// other cells

    return cell;
}

private func updateSelectedCategoryIfNeeded(cell:CategoryTableViewCell) {
    if let selectedCategory = self.selectedCategory{
        // A category has been selected!
        cell.categoryNameLabel.text = selectedCategory
        updatePicekerRowPosition(cell)
    }else{
        // no category selected!
        cell.categoryNameLabel.text = "Wybierz kategorie..."
    }
}

private func updatePicekerRowPosition(cell:CategoryTableViewCell) {
    if let index = categories.indexOf(selectedCategory!){
        cell.pickerView.selectRow(Int(index.value), inComponent: 0, animated: false)
    }
}    

识别行选择

categoryIndexPath为private let NSIndexPath

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    selectedCategory = categories[row]
    if let categoryCell = tableView.cellForRowAtIndexPath(categoryIndexPath) as? CategoryTableViewCell {
        categoryCell.categoryNameLabel.text = selectedCategory
    }
}

1 个答案:

答案 0 :(得分:1)

从我在代码中看到的内容中,您对表视图有很多误解。

我会试着更礼貌地说,但我不能。 您在代码中引用categoryCell的方式是完全错误的! UITableviewCell如果您将它们出列,则不是静态引用!

第一步:删除categoryCell变量!!!

表格视图的工作方式如下:

cellForRowAtIndexPath方法从故事板或你的笔尖获取一个单元格,重复该单元格一遍又一遍!因此,在开始时,您可能会按照自己的方式(创建对categoryCell的引用),但只要您有更多的单元格而不是适合屏幕,情况就会发生变化,因为变量将引用一个不同的细胞!

  

阅读建议:Creating and Configuring a Table View

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    var cell : UITableViewCell?
    switch(indexPath.row){
  //other cells
    case 1:
        //Kategoria
        let identifier = "category"
        // tableview checks if there is a cached cell 
        // for the identifier (reuse), 
        // if there is, it will take that one!
        cell = tableView.dequeueReusableCellWithIdentifier(identifier) as! CategoryTableViewCell
        cell.pickerView.delegate = self
        cell.pickerView.dataSource = self
        if let selectedCategory = self.selectedCategory{
            // A category has been selected!
            cell.categoryNameLabel.text = selectedCategory
        }else{
            // no category selected!
            cell.categoryNameLabel.text = "Wybierz kategorie..."
        }
        return cell
  //other cells
}

正如您在上面所看到的,我引入了一个名为selectedCategory的新变量,它将反映当前选择的类别......

在控制器中设置如下:

var selectedCategory : String?

重新加载某个部分或行或整个表时会发生的情况是,再次调用给定行的所有UITableViewDataSource方法!在某种程度上,表视图总是试图反映模型的某些状态。

您应该始终通过重新加载行/部分或整个表来反映模型中的更改(取决于更改的内容)。

因此,当您选择类别时,您可以更改模型并重新加载您的行!

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

    // update the model!
    selectedCategory = categories[row]

    // the table view now needs to know that the model changed!
    // this will trigger the dataSource method cellForRowAtIndexPath
    // and because it selectedCategory is now set, it will update 
    // your string accordingly!
    tableView.reloadRowsAtIndexPaths([/*<IndexPath of your categoryLabelCell>*/], withRowAnimation: UITableViewRowAnimation.Automatic)

}

唷!我希望有帮助...