2017-07-02 74 views
0

我正在爲用戶構建自定義界面,以在我的應用中輸入偏好設置。我正在使用example I found at AppCoda之後的展開式行。我重寫了這個例子來使用Swift 3/4,並使用代碼中的單元信息而不是從plist中讀取。Swift表中的可擴展單元 - 單元重用/出隊?

我遇到了一些單元格內容出現在屏幕上的問題。展開和摺疊的行包含文本字段以允許用戶輸入。下面的示例代碼中有四個這樣的行。

在其中一個單元格中輸入條目時,它們可能會或不會導致最後輸入的值在展開時出現在所有四個單元格中。 '額外'文本甚至會覆蓋那裏的信息。

我試過了所有我能想到的東西來擺脫這種違規的文字,但我把頭撞在牆上。我錯過了什麼?

FWIW,我現在正在其他地方尋找類似的解決方案。這裏有一個我喜歡了不少:

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

這一個看起來很有趣,但不是在斯威夫特:

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 
    } 
} 

回答

0

OMG,我拍着我的掌心我的額頭。上面的代碼中缺少一條非常重要的代碼行:

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

你能看到缺少的東西嗎?

textField?.text = nil 

這就是這一切!我正在嘲笑標籤,但不是textfield文本本身。