简体   繁体   中英

Tableview cells data is changing when I scroll vertically in swift iOS

I have developed an iOS app it has couple of tableviews. It works fine if I did not scroll, if i scroll tableview data inside cells data is changing pls make me perfect here. Here is the code below for first table which will have UISwitch and text. 在此处输入图片说明 For reference pls watch video: https://drive.google.com/open?id=1hVHnAyGnQFrhvzLSoJjeMzG6wlfxoURm

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
   if let d = self.data {
       return d.count
   }
   return  0

}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCell(withIdentifier: "cell")

    if let _ = cell {} else {
        cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
    }
    if let d = self.data {
        cell?.textLabel?.text = d[indexPath.row]
        let switchView = UISwitch(frame: .zero)
        switchView.setOn(self.isFolderIsAdded(folderName: d[indexPath.row]), animated: true)
        switchView.tag = indexPath.row // for detect which row switch Changed
        switchView.addTarget(self, action: #selector(self.switchChanged(_:)), for: .valueChanged)
        cell?.accessoryView = switchView

    }
    return cell!
}

func isFolderIsAdded(folderName:String) -> Bool{
    for   val in listOfSelectedFolder{
        if(folderName == val ){
            return true
        }
    }
    return false;
}

@objc func switchChanged(_ sender : UISwitch!){
    if let d = self.data {
        if(sender.isOn){
            self.delegate?.selectedSubFolder(name: d[sender.tag])
           } else {
            self.delegate?.deleteFilesFromFolder(folderName: d[sender.tag])
        }
    }
}

Here is the second table code which will have image view and text. I created custom cell named TableViewCell在此处输入图片说明 . For reference pls watch video: https://drive.google.com/open?id=11snH5_henOadVCVqS9bL5SZRjcZF3vEU

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableViewContent.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! TableViewCell
    if let _ = contentModel[self.currentMode]{
        tempArr1 = appendFolderName(files: contentModel[self.currentMode]!, name: self.currentMode)!

    }
    if indexPath.row < tempArr1.count {
        cell.setupCellData(text: tempArr1[indexPath.row])
    }else{
        if let res = self.getFilesFromSubFolder(contentName: self.currentMode, folderName: self.SelectedFolder) {
            cell.setupCellData(text: res[indexPath.row - tempArr1.count] )

        }
    }
    let bgColorView = UIView()
    bgColorView.backgroundColor = UIColor.gray
    cell.selectedBackgroundView = bgColorView
    return cell
}

func setupCellData(text:String) {
    let temarr = text.components(separatedBy: "@")
    let str =  temarr.last?.capitalized
    let strq = temarr.first?.lowercased()
    let newstr = strq?.components(separatedBy: "-")
    let val = newstr?.last
    let content = val!.lowercased() + "@" +  str!
    self.ContentLabel.text = content
    if ((self.ContentLabel.text?.contains("pps"))!||(self.ContentLabel.text?.contains("pptx"))!||(self.ContentLabel.text?.contains("ppt"))!){
        imageData.image = #imageLiteral(resourceName: "table_Content_ppt")
    }else if ((self.ContentLabel.text?.contains("mp4"))! || (self.ContentLabel.text?.contains("mp3"))!){
        imageData.image = #imageLiteral(resourceName: "table_Content")
    }else if (self.ContentLabel.text?.contains("pdf"))!{
        imageData.image = #imageLiteral(resourceName: "pdf_content")
    }else if (self.ContentLabel.text?.contains("url"))!{
        imageData.image = #imageLiteral(resourceName: "url_content")
    }else if (self.ContentLabel.text?.contains("exe"))!{
        imageData.image = #imageLiteral(resourceName: "application_content")
    }else if (self.ContentLabel.text?.contains("doc"))!{
        imageData.image = #imageLiteral(resourceName: "word_content")
    }else if (self.ContentLabel.text?.contains("bat"))!{
        imageData.image = #imageLiteral(resourceName: "cmd")
    }
    else if (self.ContentLabel.text?.contains("lnk"))!{
        imageData.image = #imageLiteral(resourceName: "cmd")
    }
    else if ((self.ContentLabel.text?.contains("png"))! || (self.ContentLabel.text?.contains("jpg"))! || (self.ContentLabel.text?.contains("jpeg"))! || (self.ContentLabel.text?.contains("psd"))! || (self.ContentLabel.text?.contains("tiff"))! || (self.ContentLabel.text?.contains("gif"))!) {

        imageData.image = #imageLiteral(resourceName: "img")

    }else{
        imageData.image = nil

    }

}

I have added prepareForReuse()method in tableview cell class but still result is same content is changed after scroll.

    override func prepareForReuse() {
    super.prepareForReuse()
    // Clear all content based views and their actions here
     imageData.image = nil
    ContentLabel.text = ""
}

You have to update the listOfSelectedFolder array in switchChanged .

Assuming self.data will be declared as non-optional change the method to

@objc func switchChanged(_ sender : UISwitch){
    let folderName = self.data[sender.tag]
    if sender.isOn {
        listOfSelectedFolder.append(folderName)
        self.delegate?.selectedSubFolder(name: folderName)
    } else {
       if let index = listOfSelectedFolder.index(of: folderName) {
          listOfSelectedFolder.remove(at: index)
       }
       self.delegate?.deleteFilesFromFolder(folderName: folderName)
    }
}

The other methods can be optimized

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.data.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    let folderName = self.data[indexPath.row]
    cell.textLabel?.text = folderName
    let switchView = UISwitch(frame: .zero)
    switchView.setOn(self.isFolderAdded(folderName: folderName), animated: true)
    switchView.tag = indexPath.row // for detect which row switch Changed
    switchView.addTarget(self, action: #selector(switchChanged), for: .valueChanged)
    cell.accessoryView = switchView
    return cell
}

func isFolderAdded(folderName: String) -> Bool{
    return listOfSelectedFolder.contains(folderName)
}

However it's highly recommended to use a custom struct as data model and add a isSelected property. And declare listOfSelectedFolder as a Set.

Put this in your cell class

    override func prepareForReuse() {
        super.prepareForReuse()
        // Clear all content based views and their actions here
    }

I also experienced the same issue before and I tried to add layoutIfNeeded() inside the cellForRowAt and it solved the problem.

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCell(withIdentifier: "cell")

    if let _ = cell {} else {
        cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
    }
    if let d = self.data {
        cell?.textLabel?.text = d[indexPath.row]
        let switchView = UISwitch(frame: .zero)
        switchView.setOn(self.isFolderIsAdded(folderName: d[indexPath.row]), animated: true)
        switchView.tag = indexPath.row // for detect which row switch Changed
        switchView.addTarget(self, action: #selector(self.switchChanged(_:)), for: .valueChanged)
        cell?.accessoryView = switchView
cell?.layoutIfNeeded() <--- Add this

    }
    return cell!
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM