I made a table view with a label that increments and decrements on pressing a button and another button to show the text in another label outside the UItableView. Everything works fine but when I scroll the Tableview the value resets to zero!
Before Scrolling
After Scrolling
My ViewController class
class ViewController: UIViewController{
var numArray = [Value]()
var initialValue = 0
@IBOutlet weak var tableView : UITableView!
@IBOutlet weak var lblOutput : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
for _ in 0 ... 100{
numArray.append(Value(number: initialValue))
}
self.lblOutput.text = "(initialValue)"
tableView.delegate = self
tableView.dataSource = self
tableView.reloadData()
}
}
extension ViewController : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",for: indexPath) as? ControllerTableViewCell else{fatalError("Error in creating cells")}
cell.delegate = self
cell.data = numArray[indexPath.row]
cell.lblInput.text = "(cell.data.number)"
return cell
}
}
extension ViewController : MyTableViewCellDelegate{
func DidPrint(Data: String) {
self.lblOutput.text = "(Data)"
}
}
My TableViewCell class
protocol MyTableViewCellDelegate : AnyObject {
func DidPrint(Data: String)
}
class ControllerTableViewCell: UITableViewCell {
weak var delegate : MyTableViewCellDelegate?
var data : Value!
private var counterValue = 0
@IBOutlet var lblInput : UILabel!
@IBOutlet var btnPrint : UIButton!
@IBOutlet var btnPlus : UIButton!
@IBOutlet var btnMinus : UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
@IBAction func DidPressPrint(){
self.data.number = counterValue
delegate?.DidPrint(Data: "(data.number)")
print(data.number)
}
@IBAction func DidPressPlus(){
counterValue += 1
data.number = counterValue
self.lblInput.text = "(data.number)"
}
@IBAction func DidPressMinus(){
if(counterValue > 0){
counterValue -= 1
data.number = counterValue
}
else{
counterValue = 0
data.number = 0
}
self.lblInput.text = "(data.number)"
}
}
My Data Model
import Foundation
struct Value{
var number : Int
}
2
Answers
As @El Tomato suggested, you are not updating your data source, that’s why your changes gets "forgotten" on scroll.
Try to move your
didPressPlus
,didPressMinus
anddidPressPrint
in yourViewController
class and redefine your table view delegate like below.By passing the
tag
attributes to the buttons, you can then retrieve the index of the item pressed in the functions and edit the correct data source item.Also remove the unnecessary
MyTableViewCellDelegate
.In order to move the three methods in the
ViewController
you’ll need to remove the two correspondentIBAction
from theUITableViewCell
class.Also, remove the linkage with the
ControllerTableViewCell
actions.Here is the resulting
ControllerTableViewCell
:Your TableView’s numberOfRowsInSection is using numArray as a source (numArray.count) and so is your cellForRowAt function, but your cell functions are updating your ‘data’ variable. Your ‘data’ variable is locally defined to your tableView and gets reset every time it is activated (including when you scroll).
You need to update the numArray or some other global resource to make it work. This involves using indexpath of the cell value inside the cell functions, meaning you need a way to refer to indexPath inside the cell. This article explains how to use tags or delegates, https://fluffy.es/handling-button-tap-inside-uitableviewcell-without-using-tag/.
Here’s a solution using the existing delegate.