UITableView崩溃时不记得选择

时间:2019-05-30 20:18:35

标签: swift uitableview

我有一个包含3个可折叠部分的表格视图。用户只能选择第3部分中的行,选择时该行变为绿色。但是,当此部分折叠时,所有选择都将被忘记,而当我重新打开该部分时,通常第一行始终为绿色(尽管不应如此)。有时候,其他部分在不应该使用时也会变成绿色-不确定我错了吗?

// Number of table sections
func numberOfSections(in tableView: UITableView) -> Int {
    return 3
}

// Set the number of rows
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if (self.expandedSectionHeaderNumber == section) {

        // If markscheme, create the markscheme format
        if (section == 2)
        {
            return self.markschemeRows.count
        }
        else
        {
            let arrayOfItems = self.sectionItems[section] as! NSArray
            return arrayOfItems.count
        }

    } else {
        return 0;
    }
}

// Set titles for sections
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    if (self.sectionNames.count != 0) {
        return self.sectionNames[section] as? String
    }
    return ""
}

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 44.0;
}

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat{
    return 0;
}

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    //recast your view as a UITableViewHeaderFooterView
    let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView
    header.contentView.backgroundColor = UIColor.darkGray
    header.textLabel?.textColor = UIColor.white

    if let viewWithTag = self.view.viewWithTag(kHeaderSectionTag + section) {
        viewWithTag.removeFromSuperview()
    }
    let headerFrame = self.view.frame.size
    let theImageView = UIImageView(frame: CGRect(x: headerFrame.width - 32, y: 13, width: 18, height: 18));
    theImageView.image = UIImage(named: "Chevron-Dn-Wht")
    theImageView.tag = kHeaderSectionTag + section
    header.addSubview(theImageView)

    // make headers touchable
    header.tag = section
    let headerTapGesture = UITapGestureRecognizer()
    headerTapGesture.addTarget(self, action: #selector(CaseViewController.sectionHeaderWasTouched(_:)))
    header.addGestureRecognizer(headerTapGesture)
}

// Load the table data
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
    let section = self.sectionItems[indexPath.section] as! NSArray

    cell.textLabel?.textColor = UIColor.black
    cell.selectionStyle = .none
    //cell.backgroundColor = .white

    // Get the data from different arrays depending on the section
    if indexPath.section == 2 {
        cell.textData?.text = markschemeRows[indexPath.row]

    } else {
        cell.textData?.text = section[indexPath.row] as! String

    }

    return cell
}

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {

    if indexPath.section == 0{

        if indexPath.row == 0{
            return nil
        }

    }
    else if indexPath.section == 1{

        if indexPath.row == 0{
            return nil
        }

    }
    return indexPath

}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
    let cell = tableView.cellForRow(at: indexPath)

    cell?.backgroundColor = .green
}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)

    let cell = tableView.cellForRow(at: indexPath)

    if (cell?.backgroundColor == .green)
    {
        cell?.backgroundColor = .white
    }
}


// MARK: - Expand / Collapse Methods

@objc func sectionHeaderWasTouched(_ sender: UITapGestureRecognizer) {
    let headerView = sender.view as! UITableViewHeaderFooterView
    let section    = headerView.tag
    let eImageView = headerView.viewWithTag(kHeaderSectionTag + section) as? UIImageView

    if (self.expandedSectionHeaderNumber == -1) {
        self.expandedSectionHeaderNumber = section
        tableViewExpandSection(section, imageView: eImageView!)
    } else {
        if (self.expandedSectionHeaderNumber == section) {
            tableViewCollapeSection(section, imageView: eImageView!)
        } else {
            let cImageView = self.view.viewWithTag(kHeaderSectionTag + self.expandedSectionHeaderNumber) as? UIImageView
            tableViewCollapeSection(self.expandedSectionHeaderNumber, imageView: cImageView!)
            tableViewExpandSection(section, imageView: eImageView!)
        }
    }
}

func tableViewCollapeSection(_ section: Int, imageView: UIImageView) {
    let sectionData = self.sectionItems[section] as! NSArray

    self.expandedSectionHeaderNumber = -1;
    if (sectionData.count == 0) {
        return;
    } else {
        UIView.animate(withDuration: 0.4, animations: {
            imageView.transform = CGAffineTransform(rotationAngle: (0.0 * CGFloat(Double.pi)) / 180.0)
        })
        var indexesPath = [IndexPath]()

        // If markscheme, different number needed
        if (section == 2)
        {
            for i in 0 ..< markschemeRows.count {
                let index = IndexPath(row: i, section: section)
                indexesPath.append(index)
            }
        }
        else
        {
            for i in 0 ..< sectionData.count {
                let index = IndexPath(row: i, section: section)
                indexesPath.append(index)
            }
        }

        self.tableView!.beginUpdates()
        self.tableView!.deleteRows(at: indexesPath, with: UITableView.RowAnimation.fade)
        self.tableView!.endUpdates()
    }
}

func tableViewExpandSection(_ section: Int, imageView: UIImageView) {
    let sectionData = self.sectionItems[section] as! NSArray

    if (sectionData.count == 0) {
        self.expandedSectionHeaderNumber = -1;
        return;
    } else {
        UIView.animate(withDuration: 0.4, animations: {
            imageView.transform = CGAffineTransform(rotationAngle: (180.0 * CGFloat(Double.pi)) / 180.0)
        })
        var indexesPath = [IndexPath]()

        // If markscheme, create the markscheme format
        if (section == 2)
        {
            for i in 0 ..< markschemeRows.count {
                let index = IndexPath(row: i, section: section)
                indexesPath.append(index)
            }
        }
        else
        {
            for i in 0 ..< sectionData.count {
                let index = IndexPath(row: i, section: section)
                indexesPath.append(index)
            }
        }
        self.expandedSectionHeaderNumber = section
        self.tableView!.beginUpdates()
        self.tableView!.insertRows(at: indexesPath, with: UITableView.RowAnimation.fade)
        self.tableView!.endUpdates()
    }
}

1 个答案:

答案 0 :(得分:0)

这里要理解的关键是, 单元格被重用 (当您说

时)
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell

dequeueReusableCell基本上重用了先前加载的UITableViewCell,在您的情况下,您将单元格的背景色更改为绿色

要更好地理解这一概念,请考虑阅读诸如this之类的有关重用单元格的文章

代码更改

考虑到以上几点,您应该怎么做

var backgroundColors = [UIColor](repeating: UIColor.white, count: 10)

您必须在模型中保存颜色的状态(理想情况下,您应该创建自定义结构)

现在在cellForRowAt中添加

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
    .
    .
    cell.backgroundColor = backgroundColors[indexPath.row]

    // **EDIT**
    let cellShouldBeSelected = backgroundColors[indexPath.row] == .green

    if cellShouldBeSelected {
         tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
    }
    .
    .
    return cell
}

您的didSelectRowAtdidDeselectRowAt应该更新模型

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    self.backgroundColors[indexPath.row] = .green

    tableView.reloadRows(at: [indexPath], with: .none)
}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)

    if (self.backgroundColors[indexPath.row] == .green) {
        self.backgroundColors[indexPath.row] = .white
        tableView.reloadRows(at: [indexPath], with: .none)
    }
}

第二次思考

解决方案2 推荐

从您的评论中,我看到您一次只需要选择一个单元格,假设保留一个backgroundColors数组是一个坏主意。

为所选索引声明一个整数

// -1 representing nothing is selected in the beginning 
var selectedRow = -1 

现在您的cellForRowAt看起来像

 let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell

    .
    .
    if indexPath.section == 2, indexPath.row == self.selectedRow  {
       cell.backgroundColor = .green
    } else {
       cell.backgroundColor = .white
    }
    .
    .

    return cell
}

还有您的didSelectRowAt

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
     if indexPath.section == 2 {
        self.selectedRow = indexPath.row

        tableView.reloadSections([2], with: .automatic)
     }
}

现在您可以完全删除didDeselectRowAt