首先,我是如何使用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
    }
}


脱脂细胞外观

ios - UITableView重载后重置UITableViewCell-LMLPHP

扩大的细胞外观

ios - UITableView重载后重置UITableViewCell-LMLPHP

问题

因此,当我在选择器中选择项目时,上面的标签应将其更改为文本,并且这种情况正在发生。但是,当此单元格缩小到默认高度时,替换效果消失了。我必须上下滚动才能看到,然后才能看到标签中更改的文本。

我假设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
    }
}

最佳答案

从您的代码中可以看到,您对表视图有很多误解。

我会尽量礼貌地说,但我不能。您在代码中引用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)

}


!希望对您有帮助...

09-08 01:49