2017-07-02 1 views
0

Je construis une interface personnalisée pour que l'utilisateur entre les paramètres de préférence dans mon application. J'utilise des lignes extensibles suivant un example I found at AppCoda. J'ai retravaillé cet exemple pour utiliser Swift 3/4 et utiliser les informations de la cellule à partir du code plutôt que de lire à partir d'une plist.Cellules extensibles dans la table Swift - réutilisation/suppression de cellules?

J'ai un problème avec la façon dont le contenu de certaines cellules apparaît à l'écran. Les lignes qui développent et réduisent contiennent des champs de texte pour permettre l'entrée de l'utilisateur. Il y a quatre lignes de ce type dans l'exemple de code ci-dessous.

Lorsqu'une entrée est effectuée dans l'une de ces cellules, la valeur entrée en dernier peut ou non apparaître dans les quatre cellules lorsqu'elles sont développées. Le texte «supplémentaire» écrasera même les informations qui s'y trouvent.

J'ai essayé tout ce que je pouvais penser pour me débarrasser de ce texte offensant, mais je me cognais la tête contre le mur. Qu'est-ce que je rate?

FWIW, je suis à la recherche de solutions similaires ailleurs. Voilà qui me plaît un peu:

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

Celui-ci semble intéressant, mais n'est pas à Swift:

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

Même commentaire:

https://github.com/OliverLetterer/SLExpandableTableView

Ce look très intéressant - bien soutenu - mais je n'ai pas eu le temps d'enquêter:

https://github.com/Augustyniak/RATreeView

Une demande similaire ici:

Expand cell when tapped in Swift

Un problème similaire décrit ici, mais je pense que je fais déjà ce qui est proposé?

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

Voici mon code de contrôleur de vue de la table. Je crois que le problème est dans le ...

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

... fonction, mais pour la vie de moi je ne peux pas le voir.

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 
} 

Voici le code CustomCell avec presque aucun changement par moi:

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

Répondre

0

OMG, je gifler ma paume sur mon front. Il y a une ligne très importante manquante de ce code d'en haut:

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

Pouvez-vous voir ce qui manque?

textField?.text = nil 

C'est tout ce qu'il a fallu! Je me baladais avec l'étiquette mais pas le texte du champ de texte lui-même.