Swift表中的可扩展单元格 - 单元重用/出列?

时间:2017-07-02 17:11:18

标签: swift uitableview cell expandable

我正在构建一个自定义界面,供用户在我的应用中输入首选项设置。我在example I found at AppCoda之后使用可扩展行。我重写了这个例子,使用Swift 3/4并使用代码中的单元格信息,而不是从plist中读取。

我对屏幕上出现某些细胞内容的方式有疑问。展开和折叠的行包含允许用户输入的文本字段。下面的示例代码中有四行。

当在其中一个单元格中输入条目时,它可能会也可能不会导致最后输入的值在展开时显示在所有四个单元格中。 “额外”文本甚至会覆盖属于那里的信息。

我已经尝试了所有我能想到的东西来摆脱这个令人讨厌的文字,但我正在撞墙。我错过了什么?

FWIW,我现在正在寻找其他地方的类似解决方案。这是我非常喜欢的一个:

https://github.com/jeantimex/ios-swift-collapsible-table-section-in-grouped-section

这个看起来很有趣但不在Swift中:

https://github.com/singhson/Expandable-Collapsable-TableView

相同评论:

https://github.com/OliverLetterer/SLExpandableTableView

这看起来非常有趣 - 得到很好的支持 - 但我没有时间调查:

https://github.com/Augustyniak/RATreeView

此处有类似的请求:

Expand cell when tapped in Swift

此处描述了类似的问题,但我认为我已经在做什么了?

http://www.thomashanning.com/the-most-common-mistake-in-using-uitableview/

这是我的表视图控制器代码。我相信问题出现在...中。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath):

...功能,但对于我的生活,我看不到它。

    override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    test = defineCellProps()  // This loads my hard-coded cell properties into array "test"
    configureTableView()
}

func configureTableView() {
    loadCellDescriptors()
    tblExpandable.delegate = self
    tblExpandable.dataSource = self
    tblExpandable.tableFooterView = UIView(frame: CGRect.zero)
    tblExpandable.register(UINib(nibName: "NormalCell", bundle: nil), forCellReuseIdentifier: "idCellNormal")
    tblExpandable.register(UINib(nibName: "TextfieldCell", bundle: nil), forCellReuseIdentifier: "idCellTextfield")  // There are additional cell types that are not shown and not related to the problem
}

func loadCellDescriptors() {  // Puts the data from the "test" array into the format used in the original example
    for section in 0..<ACsections.count {
        var  sectionProps = findDict(matchSection: ACsections[section], dictArray: test)
        cellDescriptors.append(sectionProps)
    }
    cellDescriptors.remove(at: 0)  // Removes the empty row
    getIndicesOfVisibleRows()        
    tblExpandable.reloadData()  // The table
}

func getIndicesOfVisibleRows() {
    visibleRowsPerSection.removeAll()
     for currentSectionCells in cellDescriptors {  // cellDescriptors is an array of sections, each containing an array of cell dictionaries
        var visibleRows = [Int]()
        let rowCount = (currentSectionCells as AnyObject).count as! Int
        for row in 0..<rowCount {  // Each row is a table section, and array of cell dictionaries
            var testDict = currentSectionCells[row]
            if testDict["isVisible"] as! Bool == true {
                visibleRows.append(row)
            }  // Close the IF
        }  //  Close row loop
        visibleRowsPerSection.append(visibleRows)
    }  //  Close section loop
}  //  end the func


func getCellDescriptorForIndexPath(_ indexPath: IndexPath) -> [String: AnyObject] {
   let indexOfVisibleRow = visibleRowsPerSection[indexPath.section][indexPath.row]
    let cellDescriptor = (cellDescriptors[indexPath.section])[indexOfVisibleRow]
    return cellDescriptor as [String : AnyObject]
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let currentCellDescriptor = getCellDescriptorForIndexPath(indexPath)
    let cell = tableView.dequeueReusableCell(withIdentifier: currentCellDescriptor["cellIdentifier"] as! String, for: indexPath) as! CustomCell
    cell.textLabel?.text = nil
    cell.detailTextLabel?.text = nil
    cell.textField?.placeholder = nil
    if currentCellDescriptor["cellIdentifier"] as! String == "idCellNormal" {
        if let primaryTitle = currentCellDescriptor["primaryTitle"] {
            cell.textLabel?.text = primaryTitle as? String
        }

        if let secondaryTitle = currentCellDescriptor["secondaryTitle"] {
            cell.detailTextLabel?.text = secondaryTitle as? String
        }
    }
    else if currentCellDescriptor["cellIdentifier"] as! String == "idCellTextfield" {
        if let primaryTitle = currentCellDescriptor["primaryTitle"] {
            if primaryTitle as! String == "" {
                cell.textField.placeholder = currentCellDescriptor["secondaryTitle"] as? String
                cell.textLabel?.text = nil

            } else {
                cell.textField.placeholder = nil
                cell.textLabel?.text = primaryTitle as? String
            }
        }

        if let secondaryTitle = currentCellDescriptor["secondaryTitle"] {
            cell.detailTextLabel?.text = "some text"
        }
        cell.detailTextLabel?.text = "some text"
//  This next line, when enabled, always puts the correct row number into each cell.
//            cell.textLabel?.text = "cell number \(indexPath.row)."
    }

    cell.delegate = self

    return cell
}

以下是CustomCell代码,我几乎没有任何更改:

import UIKit

protocol CustomCellDelegate {
func textfieldTextWasChanged(_ newText: String, parentCell: CustomCell)
}

class CustomCell: UITableViewCell, UITextFieldDelegate {

@IBOutlet weak var textField: UITextField!

let bigFont = UIFont(name: "Avenir-Book", size: 17.0)
let smallFont = UIFont(name: "Avenir-Light", size: 17.0)
let primaryColor = UIColor.black
let secondaryColor = UIColor.lightGray

var delegate: CustomCellDelegate!

override func awakeFromNib() {
    super.awakeFromNib()          // Initialization code

    if textLabel != nil {
        textLabel?.font = bigFont
        textLabel?.textColor = primaryColor
    }

    if detailTextLabel != nil {
        detailTextLabel?.font = smallFont
        detailTextLabel?.textColor = secondaryColor
    }

    if textField != nil {
        textField.font = bigFont
        textField.delegate = self
    }        
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    // Configure the view for the selected state
}

override func prepareForReuse() {  // I added this and it did not help
    super.prepareForReuse()
    textLabel?.text = nil
    detailTextLabel?.text = nil
    textField?.placeholder = nil
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if delegate != nil {
        delegate.textfieldTextWasChanged(textField.text!, parentCell: self)
    }
    return true
  }
}

1 个答案:

答案 0 :(得分:0)

天啊,我把手掌贴在额头上。上面的代码中缺少一条非常重要的行:

override func prepareForReuse() {
super.prepareForReuse()
textLabel?.text = nil
detailTextLabel?.text = nil
textField?.placeholder = nil
}

你能看到缺少的东西吗?

textField?.text = nil

这就是全部!我正在讨论标签而不是文本字段本身。