在 table 视图单元格中使用步进器 - 但返回到 VC 的数据未正确更新
Using a stepper in a table view cell - but the data returning to the VC is not updating correctly
我正在尝试创建一个配置屏幕,以便用户可以设置他或她想要进行的锻炼次数。我设法将表格视图添加到空白视图控制器,但存在一些风格限制 - 例如根据单元格数量展开和折叠表格视图。
所以我想我会在 tableviewcontroller
中设置屏幕。现在一切顺利,直到我到达我想要 section 0
、cell 1
中的 Stepper 来增加和减少 [= 中的行数的地步=18=]。它的工作范围是数据数组(workouts[]
)用最新值(在 cellForRowAt:indexPath
方法中)更新视图控制器,而视图控制器又用(假定的)最新值更新 numberOfRowsInSection workouts.count
.
然而,事实证明 workouts.count
保存了步进器最后更新数组之前的计数。
现在,我已经尝试了一些解决方法,但我仍然无法使 numberOfRowsInSection
方法正确更新 - 在我看来,Workouts 数组未在视图控制器中更新最新值,而不是之前的设定值。
这是我的视图控制器:
class AViewController: UITableViewController {
//MARK: Properties
@IBOutlet weak var aTableView: UITableView!
var sections: [String] = ["", "Set Up Circuits"]
var workouts: [Exercise] = []
//MARK: Initialisation
override func viewDidLoad() {
super.viewDidLoad()
workouts = [Exercise(name: "Circuit 1", timeMinutes: 2)]
self.tableView.delegate = self
self.tableView.dataSource = self
}
//MARK: Table Config
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sections[section]
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
switch section {
case 0:
return 0.1
default:
return 32.0
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch indexPath.section {
case 0:
return 60
default:
return 44
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var numberOfRowsInSection: Int = 0
switch section {
case 0:
numberOfRowsInSection = 1
default:
numberOfRowsInSection = workouts.count
//numberOfRowsInSection = 1
}
print(numberOfRowsInSection, "number of rows in section", section)
return numberOfRowsInSection
}
//MARK: Table Protocols
override func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.section {
//Setting layout for circuit number config
case 0:
let cell = aTableView.dequeueReusableCell(withIdentifier: "ACircuitTableViewCell") as! ACircuitTableViewCell
cell.tableView = self.aTableView
self.workouts = cell.workouts
print(workouts.count, " VC workouts array count")
return cell
//Setting layout for circuit cells
default:
let cell = aTableView.dequeueReusableCell(withIdentifier: "ATableViewCell") as! ATableViewCell
cell.aLabel.text = workouts[indexPath.row].getName()
cell.aDetail.text = "Tap here to configure"
return cell
}
}
这是我的 ACircuitTableViewCell:
class ACircuitTableViewCell: UITableViewCell {
//MARK: Properties
@IBOutlet weak var circuitNumber: UILabel!
@IBOutlet weak var circuitLabel: UILabel!
@IBOutlet weak var circStepper: UIStepper!
var tableView: UITableView!
// var updateCallback : ((_ updateList: Bool)-> Void)?
//var exercises: [Exercise]?
var anArray: [Exercise] = []
var workouts: [Exercise] = [Exercise(name: "Circuit 1", timeMinutes: 2)]
var workoutsCount: Int = 1
var indexPath: NSIndexPath = NSIndexPath(row: 0, section: 1)
//MARK: Original Functions
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
circuitNumber.text = String(workouts.count)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
@IBAction func valueChanged(_ sender: AnyObject) {
print("Method .valueChanged activated")
//Update circuitNumber label
circuitNumber.text = String(Int(circStepper.value))
//View pre-array-update status of variables
print(workouts.count, "anArray before appending")
print(circStepper.value, "stepper value before appending")
print(circuitNumber.text, "circuitNumber")
//Update workouts array
if workouts.count < Int(circStepper.value) {
workouts.append(Exercise(name: "Circuit \(Int(circStepper.value))", timeMinutes: 2))
print(workouts.count, "after appending")
tableView.reloadData()
print(workouts.count, "new workout.count")
}
print(workouts.count, "workouts.count")
print("Method .valueChanged completed")
}
这是从应用程序加载到在步进器 + 按钮上轻按三下到控制台的输出。
1 number of rows in section 1
1 number of rows in section 0
1 number of rows in section 1
1 number of rows in section 0
1 number of rows in section 1
1 number of rows in section 0
1 VC workouts array count
Method .valueChanged activated
1 anArray before appending
2.0 stepper value before appending
Optional("2") circuitNumber
2 after appending
1 number of rows in section 1
1 number of rows in section 0
2 new workout.count
2 workouts.count
Method .valueChanged completed
2 VC workouts array count
Method .valueChanged activated
2 anArray before appending
3.0 stepper value before appending
Optional("3") circuitNumber
3 after appending
2 number of rows in section 1
1 number of rows in section 0
3 new workout.count
3 workouts.count
Method .valueChanged completed
3 VC workouts array count
Method .valueChanged activated
3 anArray before appending
4.0 stepper value before appending
Optional("4") circuitNumber
4 after appending
3 number of rows in section 1
1 number of rows in section 0
4 new workout.count
4 workouts.count
Method .valueChanged completed
4 VC workouts array count
Method .valueChanged activated
4 anArray before appending
5.0 stepper value before appending
Optional("5") circuitNumber
5 after appending
4 number of rows in section 1
1 number of rows in section 0
5 new workout.count
5 workouts.count
Method .valueChanged completed
5 VC workouts array count
您应该在控制器中处理步进器回调并在那里更改 viewController 的数据源。
在视图控制器中处理单元格事件的最常见方法是使用委托,就像我在此处描述的那样:
或者,您可以在 cellForRow
方法中添加带有 self
目标的操作:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! TableViewCell
cell.stepper?.tag = indexPath.row
cell.stepper?.addTarget(self, action: #selector(stepperValueChanged(_:)), for: .valueChanged)
return cell
}
func stepperValueChanged(_ stepper: UIStepper) {
//use stepper.tag as index to fetch an object from your dataSource
let workout = dataSource[stepper.tag]
}
我正在尝试创建一个配置屏幕,以便用户可以设置他或她想要进行的锻炼次数。我设法将表格视图添加到空白视图控制器,但存在一些风格限制 - 例如根据单元格数量展开和折叠表格视图。
所以我想我会在 tableviewcontroller
中设置屏幕。现在一切顺利,直到我到达我想要 section 0
、cell 1
中的 Stepper 来增加和减少 [= 中的行数的地步=18=]。它的工作范围是数据数组(workouts[]
)用最新值(在 cellForRowAt:indexPath
方法中)更新视图控制器,而视图控制器又用(假定的)最新值更新 numberOfRowsInSection workouts.count
.
然而,事实证明 workouts.count
保存了步进器最后更新数组之前的计数。
现在,我已经尝试了一些解决方法,但我仍然无法使 numberOfRowsInSection
方法正确更新 - 在我看来,Workouts 数组未在视图控制器中更新最新值,而不是之前的设定值。
这是我的视图控制器:
class AViewController: UITableViewController {
//MARK: Properties
@IBOutlet weak var aTableView: UITableView!
var sections: [String] = ["", "Set Up Circuits"]
var workouts: [Exercise] = []
//MARK: Initialisation
override func viewDidLoad() {
super.viewDidLoad()
workouts = [Exercise(name: "Circuit 1", timeMinutes: 2)]
self.tableView.delegate = self
self.tableView.dataSource = self
}
//MARK: Table Config
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sections[section]
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
switch section {
case 0:
return 0.1
default:
return 32.0
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch indexPath.section {
case 0:
return 60
default:
return 44
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var numberOfRowsInSection: Int = 0
switch section {
case 0:
numberOfRowsInSection = 1
default:
numberOfRowsInSection = workouts.count
//numberOfRowsInSection = 1
}
print(numberOfRowsInSection, "number of rows in section", section)
return numberOfRowsInSection
}
//MARK: Table Protocols
override func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.section {
//Setting layout for circuit number config
case 0:
let cell = aTableView.dequeueReusableCell(withIdentifier: "ACircuitTableViewCell") as! ACircuitTableViewCell
cell.tableView = self.aTableView
self.workouts = cell.workouts
print(workouts.count, " VC workouts array count")
return cell
//Setting layout for circuit cells
default:
let cell = aTableView.dequeueReusableCell(withIdentifier: "ATableViewCell") as! ATableViewCell
cell.aLabel.text = workouts[indexPath.row].getName()
cell.aDetail.text = "Tap here to configure"
return cell
}
}
这是我的 ACircuitTableViewCell:
class ACircuitTableViewCell: UITableViewCell {
//MARK: Properties
@IBOutlet weak var circuitNumber: UILabel!
@IBOutlet weak var circuitLabel: UILabel!
@IBOutlet weak var circStepper: UIStepper!
var tableView: UITableView!
// var updateCallback : ((_ updateList: Bool)-> Void)?
//var exercises: [Exercise]?
var anArray: [Exercise] = []
var workouts: [Exercise] = [Exercise(name: "Circuit 1", timeMinutes: 2)]
var workoutsCount: Int = 1
var indexPath: NSIndexPath = NSIndexPath(row: 0, section: 1)
//MARK: Original Functions
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
circuitNumber.text = String(workouts.count)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
@IBAction func valueChanged(_ sender: AnyObject) {
print("Method .valueChanged activated")
//Update circuitNumber label
circuitNumber.text = String(Int(circStepper.value))
//View pre-array-update status of variables
print(workouts.count, "anArray before appending")
print(circStepper.value, "stepper value before appending")
print(circuitNumber.text, "circuitNumber")
//Update workouts array
if workouts.count < Int(circStepper.value) {
workouts.append(Exercise(name: "Circuit \(Int(circStepper.value))", timeMinutes: 2))
print(workouts.count, "after appending")
tableView.reloadData()
print(workouts.count, "new workout.count")
}
print(workouts.count, "workouts.count")
print("Method .valueChanged completed")
}
这是从应用程序加载到在步进器 + 按钮上轻按三下到控制台的输出。
1 number of rows in section 1
1 number of rows in section 0
1 number of rows in section 1
1 number of rows in section 0
1 number of rows in section 1
1 number of rows in section 0
1 VC workouts array count
Method .valueChanged activated
1 anArray before appending
2.0 stepper value before appending
Optional("2") circuitNumber
2 after appending
1 number of rows in section 1
1 number of rows in section 0
2 new workout.count
2 workouts.count
Method .valueChanged completed
2 VC workouts array count
Method .valueChanged activated
2 anArray before appending
3.0 stepper value before appending
Optional("3") circuitNumber
3 after appending
2 number of rows in section 1
1 number of rows in section 0
3 new workout.count
3 workouts.count
Method .valueChanged completed
3 VC workouts array count
Method .valueChanged activated
3 anArray before appending
4.0 stepper value before appending
Optional("4") circuitNumber
4 after appending
3 number of rows in section 1
1 number of rows in section 0
4 new workout.count
4 workouts.count
Method .valueChanged completed
4 VC workouts array count
Method .valueChanged activated
4 anArray before appending
5.0 stepper value before appending
Optional("5") circuitNumber
5 after appending
4 number of rows in section 1
1 number of rows in section 0
5 new workout.count
5 workouts.count
Method .valueChanged completed
5 VC workouts array count
您应该在控制器中处理步进器回调并在那里更改 viewController 的数据源。
在视图控制器中处理单元格事件的最常见方法是使用委托,就像我在此处描述的那样:
或者,您可以在
cellForRow
方法中添加带有self
目标的操作:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! TableViewCell
cell.stepper?.tag = indexPath.row
cell.stepper?.addTarget(self, action: #selector(stepperValueChanged(_:)), for: .valueChanged)
return cell
}
func stepperValueChanged(_ stepper: UIStepper) {
//use stepper.tag as index to fetch an object from your dataSource
let workout = dataSource[stepper.tag]
}