Swift - Increment Label with Stepper in TableView Cell
Easiest solution (simplyfied):
Create a model
BuyStat
with a propertypurchaseAmount
(it's crucial to be a class).
You are strongly discouraged from using multiple arrays as data sourceclass BuyStat {
var purchaseAmount = 0.0
init(purchaseAmount : Double) {
self.purchaseAmount = purchaseAmount
}
}In the view controller create a data source array
var stats = [BuyStat]()
In
viewDidLoad
create a few instances and reload the table viewstats = [BuyStat(purchaseAmount: 12.0), BuyStat(purchaseAmount: 20.0)]
tableView.reloadData()In the custom cell create a property
buyStat
to hold the current data source item with an observer to update stepper and label whenbuyStat
is setclass BuyStatsCell: UITableViewCell {
@IBOutlet weak var purchaseAmount: UILabel!
@IBOutlet weak var addSubtract: UIStepper!
var buyStat : BuyStat! {
didSet {
addSubtract.value = buyStat.purchaseAmount
purchaseAmount.text = String(buyStat.purchaseAmount)
}
}
@IBAction func stepperAction(_ sender: UIStepper) {
buyStat.purchaseAmount = sender.value
self.purchaseAmount.text = String(sender.value)
}
}In
cellForRowAtIndexPath
get the data source item and pass it to the cellfunc tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BuyStatsTabCell", for: indexPath) as! BuyStatsCell
cell.buyStat = stats[indexPath.row]
return cell
}
The magic is: When you are tapping the stepper the label as well as the data source array will be updated. So even after scrolling the cell will get always the actual data.
With this way you don't need protocols or callback closures. It's only important that the model is a class to have reference type semantics.
Updating label in UITableViewCell with UIStepper in Swift
Initially FoodTableViewCell
is the ONLY target for UIStepper
value changed (looking at @IBAction
inside FoodTableViewCell
).
When you dequeue a cell to display on screen, you call -
cell.stepper.addTarget(self, action: #selector(stepperValueChanged(_:)), for: .valueChanged)
which causes your ShoppingListVC
instance to be added as an additional target every time a cellForRow
call is executed.
Things to fix :
- Remove all of your
NotificationCenter
related code from both classes. - Remove
cell.stepper.addTarget()
line as well.
This would give you a better idea of why it is happening this way. Update your question with these changes in case you still don't have what you want.
UPDATE
// Inside cellForRow
cell.stepper.value = food.serving
Stepper on tableview cell (swift)
As mentioned by @A-Live, your component is being reused and so need to be updated.
So in your view controller:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "reviewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ReviewTableViewCell
var imageView: UIImageView?
let photoG = self.photos[indexPath.row]
imageView = cell.contentView.viewWithTag(1) as? UIImageView
//let layout = cell.goodiesImage
let tag = indexPath.row // +1
cell.tag = tag
photoG.fetchImageWithSize(CGSize(width: 1000, height: 1000), completeBlock: { image, info in
if cell.tag == tag {
imageView?.image = image
cell.goodiesImage.image = image
}
})
cell.countStepper.value = XXX[indexPath.row].value; //Here you update your view
cell.stepperLabel.text = "x \(Int(cell.countStepper.value))" //And here
And
func stepperButton(sender: ReviewTableViewCell) {
if let indexPath = tableView.indexPathForCell(sender){
print(indexPath)
XXX[sender.tag].value = sender.counterStepper.value //Here you save your updated value
}
Swift - Stepper in TableViewCell - Action not Responding
You've disabled the user interaction in your cell for row at index method:
cell.isUserInteractionEnabled = false;
You should remove this line.
Swift Delegation - Use Stepper in Tableview Cell to Update Label in Separate Class
If you are using a dynamic UITableView
, you might try the following inside your cellForRowAtIndexPath
:
- When you init your cell with
dequeueCellWithReuseIdentifier
, cast it as aBuyStatsCell
(maybe withas! BuyStatsCell
) to get access to its class variables. - Set up the delegation with
cell.setRemaining = self
. The use ofself
assumes that your tableView'scellForRowAtIndexPath
is inside theBuyStats
viewController class. If it's not, you would want to get the reference for yourBuyStats
object in the class where your tableView's code lives, and use that reference in place ofself
, likecell.setRemaining = /*yourBuyStatsObjectReferenceGoesHere*/
.
Hope that helps.
Related Topics
Xcode 7.3.1 Hangs on "Copying Swift Standard Libraries"
Compiler Error When Comparing Values of Enum Type with Associated Values
Convert Between Decimal, Binary and Hexadecimal in Swift
Uitableviewautomaticdimension Not Working for Resizing Cell Height
What Is the Use of "Static" Keyword If "Let" Keyword Used to Define Constants/Immutables in Swift
Scrollview + Navigationview Animation Glitch Swiftui
Swift Spritekit Adding Button Programmatically
Should Conditional Compilation Be Used to Cope With Difference in Cgfloat on Different Architectures
In Xcode 6.1. 'Uiimage' Does Not Have a Member Named 'Size' Error
How to Draw Text in PDF Context in Swift