Swift 如何保持对象';使用UITableView时的引用?
我面临的问题可能是对可重用单元的概念缺乏理解。我有30行要创建,每个行都有一个UISwitchSwift 如何保持对象';使用UITableView时的引用?,swift,uitableview,Swift,Uitableview,我面临的问题可能是对可重用单元的概念缺乏理解。我有30行要创建,每个行都有一个UISwitch 当我切换其中一个开关时,它的行为会影响其他开关。要点是:据我所知,iOS并不是一次创建所有单元格,而是在上下滚动TableView时等待重用单元格 我如何保存这些重用对象的副本,并告诉iOS为交换机设置正确的值 我曾考虑将这些单元格附加到[UISwitch]上,但我无法将所有30个单元格都放在那里,看: ... var switches = [UISwitch]() ... override f
当我切换其中一个开关时,它的行为会影响其他开关。要点是:据我所知,iOS并不是一次创建所有单元格,而是在上下滚动TableView时等待重用单元格 我如何保存这些重用对象的副本,并告诉iOS为交换机设置正确的值 我曾考虑将这些单元格附加到[UISwitch]上,但我无法将所有30个单元格都放在那里,看:
...
var switches = [UISwitch]()
...
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Field10Cell", for: indexPath) as! Field10TableViewCell
...
//cell.value is a UISwitch
if !switches.contains(cell.value) {
switches.append(cell.value)
}
return cell
}
您可以创建一个集合来存储开关被按下的单元格的索引
var activeSwitches = Set<IndexPath>()
如果需要检查开关是否已激活,只需检查其容器单元格的indexPath是否位于活动开关中,如下所示:
if activeSwitches.contains(indexPath) {
// do something
}
为了了解用户何时按下特定开关,我建议使用以下选项:
protocol Field10Delegate {
func didChangeSwitch(value: Bool, indexPath: IndexPath)
}
class Field10TableViewCell {
var delegate: Field10Delegate?
var indexPath: IndexPath?
@IBOutlet weak var fieldSwitch: UISwitch! // Can't use 'switch' as a variable name
@IBAction func switchValueChanged(_ sender: UISwitch) {
if let indexPath = indexPath {
delegate?.didChangeSwitch(value: sender.isOn, indexPath: indexPath)
}
}
let cell = tableView.dequeueReusableCell(withIdentifier: "Field10Cell", for: indexPath) as! Field10TableViewCell
cell.delegate = self
cell.indexPath = indexPath
extension ViewController: Field10Delegate {
/* Whenever a switch is pressed on any cell, this delegate will
be called. This is a good place also to trigger a update to
your UI if it has to respond to switch changes.
*/
func didChangeSwitch(value: Bool, indexPath: IndexPath) {
if value {
activeSwitches.insert(indexPath)
} else {
activeSwitches.remove(indexPath)
}
updateUI()
}
}
通过以上操作,您随时都可以知道哪些开关处于活动状态,并且可以使用此信息处理已退出队列的单元格。您可以创建一个集合,用于存储按下开关的单元格的索引
var activeSwitches = Set<IndexPath>()
如果需要检查开关是否已激活,只需检查其容器单元格的indexPath是否位于活动开关中,如下所示:
if activeSwitches.contains(indexPath) {
// do something
}
为了了解用户何时按下特定开关,我建议使用以下选项:
protocol Field10Delegate {
func didChangeSwitch(value: Bool, indexPath: IndexPath)
}
class Field10TableViewCell {
var delegate: Field10Delegate?
var indexPath: IndexPath?
@IBOutlet weak var fieldSwitch: UISwitch! // Can't use 'switch' as a variable name
@IBAction func switchValueChanged(_ sender: UISwitch) {
if let indexPath = indexPath {
delegate?.didChangeSwitch(value: sender.isOn, indexPath: indexPath)
}
}
let cell = tableView.dequeueReusableCell(withIdentifier: "Field10Cell", for: indexPath) as! Field10TableViewCell
cell.delegate = self
cell.indexPath = indexPath
extension ViewController: Field10Delegate {
/* Whenever a switch is pressed on any cell, this delegate will
be called. This is a good place also to trigger a update to
your UI if it has to respond to switch changes.
*/
func didChangeSwitch(value: Bool, indexPath: IndexPath) {
if value {
activeSwitches.insert(indexPath)
} else {
activeSwitches.remove(indexPath)
}
updateUI()
}
}
通过以上内容,您随时都可以知道哪些开关处于活动状态,并且您可以使用此信息处理排队的单元格。“当我切换其中一个开关时,其行为应该会影响其他29个开关。”您可以进一步解释一下吗?假设我切换了开关一。在“onvaluechanged”上,我想禁用所有其他29个开关,但我不能,因为我还没有它们的实例(我猜),您的想法是错误的。如果在切换一个开关时所有开关都应该具有相同的状态,则声明一个布尔属性以保持当前状态和一个
iAction
。将单元格中的按钮连接到操作。如果开关更改了值,请更新boolean属性,重新加载表视图并相应地在cellForRow中设置开关的状态。@vadian我应该在哪里声明该变量?在单元格或tableview类中?在控制器中。“当我切换其中一个开关时,它的行为应该会影响其他29个开关。”请您对此进行详细解释。假设我切换开关一。在“onvaluechanged”上,我想禁用所有其他29个开关,但我不能,因为我还没有它们的实例(我猜),您的想法是错误的。如果在切换一个开关时所有开关都应该具有相同的状态,则声明一个布尔属性以保持当前状态和一个iAction
。将单元格中的按钮连接到操作。如果开关更改了值,请更新boolean属性,重新加载表视图并相应地在cellForRow中设置开关的状态。@vadian我应该在哪里声明该变量?在单元格中或在控制器的tableview类中。==true
是冗余的<代码>如果值{而且顺便说一句,无需为交换机添加IBOutlet。只需使用sender即可。UISwitch没有value属性。您应该使用它的isOn属性。sender.isOn
谢谢您的更正@LeoDabus!我是按内存编码的,容易出错:-/@FelipeFerri通常不需要。但这不会有什么坏处:)通常您是t强烈建议不要保留索引路径数组/集合。例如,当您通过拖放实现行重新排序时,索引路径可以在不调用cellForRow
的情况下更改。==true
是多余的。如果值{
而且顺便说一句,无需为交换机添加IBOutlet。只需使用sender即可。UISwitch没有value属性。您应该使用它的isOn属性。sender.isOn
谢谢您的更正@LeoDabus!我是按内存编码的,容易出错:-/@FelipeFerri通常不需要。但这不会有什么坏处:)通常您是强烈建议不要保留索引路径数组/集合。例如,当您通过拖放实现行重新排序时,索引路径可以在不调用cellForRow
的情况下更改。