Tableview动态开关有问题,如果我选择开关并立即启动它不能在swift中启动

问题描述 投票:1回答:3

我创建了一个UITableView并动态地将开关添加到每个单元格中,基础是必需的。如果我选择一个开关并将其打开并立即选择下一个开关然后将其打开,那么它的状态会出现问题,而且之前选择的开关正在关闭,只有当我快速选择所有开关时才会发生这种情况。 。

enter image description here

这里的图像是我根据数据动态添加所有开关,如果我在第一个开关上,它将数据加载到另一个表中。但如果我快速选择所有开关并将它们打开,某些开关只会卡在关闭状态。如果我点击表的外面它消失,如果我再次加载表,那时我可以看到所有选择和先前启用(打开)开关关闭(不是所有,但随机发生)

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])
        }
    }
}
ios swift xcode uitableview swift4.2
3个回答
2
投票

这是一个重用问题。滚动tableView时,将重新使用该单元格。它上面的开关将被重置。

您需要遵循MVC设计模式。使用模型来帮助你。像这样

class CellModel {
  var name = ""
  var switchOn = false
}

var dataSource = [CellModel]()

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CustomCell
    cell.model = dataSource[indexPath.row]
    return cell
}
class CustomCell: UITableViewCell {

  var model: CellModel? {
     didSet {
     switchView.isOn = model?.switchOn ?? false
    }
  }
  init(xxxx) {
     switchView.addTarget(self, action:#selector(self.switchChanged(_:)), for: .valueChanged)
  }


  @objc func switchChanged(_ sender : UISwitch!){
       model.switchOn = sender.isOn
   }
  }

0
投票

重用uitableViewCell时务必记得使用。

1- tableViewCell类中的prepareForReuse方法

2-如果您要更新else中的任何UI,请特别为所有if conditionsif condition条件

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

}else{
// Update your UI if data not found like turn your switch off etc ... 
    }
    return cell!
}

3-或者在Xcode 9.0模拟器更新后,你的模拟器可能会出现问题,因为它们直到Xcode 8.X


0
投票

我尝试了你的代码有一些变化,它工作正常。这不是tableView.dequeueReusableCell的问题。请尝试以下代码。

import UIKit

class FirstViewController: UIViewController,UITableViewDelegate, UITableViewDataSource{



@IBOutlet weak var tableView: UITableView!
var listOfSelectedFolder = ["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]
var listOfSelectedFolder2 = ["sample text 0","sample text 1","sample text 2","sample text 4","sample text 5","sample text 6","sample text 7","sample text 8","sample text 9","sample text 10","sample text 11","sample text 12","sample text 13","sample text 14","sample text 15","sample text 16","sample text 17","sample text 18","sample text 19","sample text 20","sample text 21","sample text 22","sample text 23","sample text 24","sample text 25","sample text 26","sample text 27","sample text 28","sample text 29","sample text 30","sample text 31","sample text 32","sample text 33","sample text 34","sample text 35","sample text 36","sample text 37","sample text 38","sample text 39","sample text 40"]

override func viewDidLoad() {
    super.viewDidLoad()
    self.tableView.delegate = self
    self.tableView.dataSource = self
    // Do any additional setup after loading the view, typically from a nib.
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

/// tableview datasouce methodes

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return listOfSelectedFolder2.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 50
}

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

    if let _ = cell {} else {
        cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
    }
    let foldername = listOfSelectedFolder2[indexPath.row]
        cell?.textLabel?.text = foldername
        let switchView = UISwitch(frame: .zero)
        switchView.setOn(self.isFolderIsAdded(folderName: foldername), 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{

    return listOfSelectedFolder.contains(folderName);
}

@objc func switchChanged(_ sender : UISwitch!){
        if(sender.isOn){

            self.listOfSelectedFolder.insert(self.listOfSelectedFolder2[sender.tag], at: sender.tag)
        } else {
            self.listOfSelectedFolder.remove(at: sender.tag)
            self.listOfSelectedFolder.insert("", at: sender.tag)
        }
}
}

如果您仍然遇到相同的问题,可能会在后台线程上发生UI更新。因此,请确保UI更新代码在主线程上运行。

dispatch_async(dispatch_get_main_queue(), {code})

要么

DispatchQueue.main.async {code}
© www.soinside.com 2019 - 2024. All rights reserved.