【问题标题】:UISwitch in custom UITableViewCell Reuse Issue自定义 UITableViewCell 重用问题中的 UISwitch
【发布时间】:2017-12-19 02:10:32
【问题描述】:

问题如下:我有一个带有自定义单元格的表格视图。该单元格包含一个标签和一个 UISwitch。我已将 label.text 值设置为数组,但 UISwitch 正在被重用。

示例:如果我在第一行切换开关,第 5 行将启用,如果我滚动它会继续重复使用单元格并导致问题。

视频:https://vimeo.com/247906440

视图控制器:

class ViewController: UIViewController {

    let array = ["One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten"]

    @IBOutlet weak var tableView: UITableView!
    override func viewDidLoad() {
        super.viewDidLoad()

    }

}

extension ViewController: UITableViewDelegate, UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
        cell.label.text = array[indexPath.row]
        return cell
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return array.count
    }
}

自定义单元格:

class CustomTableViewCell: UITableViewCell {

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var toggleSwitch: UISwitch!

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

}

我意识到没有代码尝试存储这些数据,因为我没有成功。任何想法都会有所帮助。该项目目前使用 MVC 模型,我相信这是答案,但需要一些帮助。

【问题讨论】:

  • toggleSwitch 的开/关状态保存在哪里?由于它可以在您滚动UITableView 的任何时候重复使用,因此我建议您不要依赖任何IBOutlet。您应该实现一个模型来存储信息,然后将该模型用于injecting 您需要的 UI。

标签: ios swift uitableview uiswitch


【解决方案1】:

我建议您创建 cellViewModel 类并保留它的数组,而不仅仅是字符串。你的 cellViewModel 可能看起来像,

class CellViewModel {
 let title: String
 var isOn: Bool

init(withText text: String, isOn: Bool = false /* you can keep is at by default false*/) {
    self.title = text
    self.isOn = isOn
} 

现在,构建 CellViewModel 数组

let array =["One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten"]
var cellViewModels = [CellViewModel]()
for text in array {
    let cellViewModel = CellViewModel(withText: text)
    cellViewModels.append(cellViewModel)
}

将您的 tableVieDelegate 函数更改为:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
    let cellViewModel = cellViewModels[indexPath.row]
    cell.label.text = cellViewModel.title
    cell.toggleSwitch.isOn = cellViewModel.isOn
    cell.delegate = self
    return cell
}

在您的自定义单元类中,添加此协议:

protocol CellActionDelegate: class {
    func didChangeSwitchStateOnCell(_ cell: CustomTableViewCell)
}

在您的自定义单元格中添加委托作为属性,

weak var delegate: CellActionDelegate?

另外,在切换开关时,添加这一行,

delegate?.didChangeSwitchStateOnCell(self)

现在,您的 viewController 应该注册并监听这个委托: 我添加了行 cellForRowAtIndexPath 来注册代表。要监听这个委托,请在你的 VC 中添加这个函数。

func didChangeSwitchStateOnCell(_ cell: CustomTableViewCell) {
    let indexPath = tableView.indexPath(for: cell)
    cellViewModels[indexPath.row].isOn = cell.toggleSwitch.isOn
}

【讨论】:

  • 这会像从将 isOn 布尔值分配为 true 的开关中的 IBOutlet 一样简单吗?无论如何,您可以将那部分添加到您的答案中吗?非常感谢!
  • 您的手机将监听 Switch 操作。您需要将此更改委托给 VC。当然。让我为你添加它。
【解决方案2】:

例如开始创建模型:

struct item {
    var id: String
    var name: String
    var isActivated: Bool

    init(id: String, name: String, isActivated: Bool) {
        self.id = id
        self.name = name
        self.isActivated = isActivated
    }

}

let item1 = item(id: "1", name: "One", isActivated: false)
let item2 = ...........
let item3 = ...........
let items [item1, item2, item3]

有了它,你可以触发布尔值,如果它被激活了。

我想你还得看看https://developer.apple.com/documentation/uikit/uitableviewcell/1623223-prepareforreuse

【讨论】:

  • 这是一个很好的答案,但我将使用 Makund 的,因为它坚持我项目其余部分的 MVC 模型。非常感谢您的帮助:)
猜你喜欢
  • 1970-01-01
  • 2010-11-22
  • 2014-03-07
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多