Custom TableViewCell lose its own variable when scrolling - ios

I have the following Custom TableViewCell
The red(minus) and green(plus) button counts the left label "1"(in code snippet var myQuantity). If I scroll up and down in the tableView the variable myQuantity is always reset to 1 for selected cells.
I read that I have to set the myQuantity in the cellForRowAt method. But how can I set the cell value with its own class variable when its changed via green and red button?
Here my Custom Cell Class:
class ArticleTableViewCell: UITableViewCell {
#IBOutlet var leftLabel: UILabel!
#IBOutlet var rightLabel: UILabel!
#IBOutlet var quantityLabel: UILabel!
var myQuantity = 0
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.quantityLabel.text = String(self.myQuantity)
self.leftLabel.sizeToFit()
self.rightLabel.sizeToFit()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
if selected {
self.myQuantity = 1
} else {
self.myQuantity = 0
}
self.quantityLabel.text = String(self.myQuantity)
}
#IBAction func addButton(_ sender: UIButton) {
if !self.isSelected { return }
self.myQuantity += 1
self.quantityLabel.text = String(self.myQuantity)
}
#IBAction func minusButton(_ sender: UIButton) {
if !self.isSelected { return }
if self.myQuantity == 1 { return }
self.myQuantity -= 1
self.quantityLabel.text = String(self.myQuantity)
}}
Here the cellForRowAt Method in my ViewController:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "customArticleCell", for: indexPath) as? ArticleTableViewCell {
let name: String! = categoryArticles[indexPath.row].name
let price = categoryArticles[indexPath.row].price
let price2f = String(format: "%.2f", price)
cell.accessoryType = .none
cell.leftLabel.text = name!
cell.rightLabel.text = "\(price2f) €"
if cell.isSelected {
cell.accessoryType = .checkmark
}
return cell
}
}

class ArticleTableViewCell: UITableViewCell {
#IBOutlet var leftLabel: UILabel!
#IBOutlet var rightLabel: UILabel!
#IBOutlet var quantityLabel: UILabel!
var addAction: (()->())?
var minusAction: (()->())?
override func awakeFromNib() {
super.awakeFromNib()
self.selectionStyle = .none
}
func setupCellWith(data: CategoryArticle) {
self.accessoryType = (data.isSelected == true) ? .checkmark : .none
self.leftLabel.text = data.name
let price2f = String(format: "%.2f", data.price)
self.rightLabel.text = "\(price2f) €"
}
#IBAction func addButton(_ sender: UIButton) {
self.addAction?()
}
#IBAction func minusButton(_ sender: UIButton) {
self.minusAction?()
}
}
struct CategoryArticle {
let name: String
let price: Double
var isSelected: Bool?
var quantity: Int?
}
let categoryArticles: [CategoryArticle] = []
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customArticleCell", for: indexPath) as! ArticleTableViewCell
let categoryArticle = categoryArticles[indexPath.row]
cell.setupCellWith(data: categoryArticle)
cell.minusAction = { [weak self] in
// Action you want to do like decrease the count in the model at indexPath.row and set selection in th model too and reload the tableView cell
}
cell.addAction = { [weak self] in
// Action you want to do like increase the count in the model at indexPath.row and set selection in th model too and reload the tableView cell
}
return cell
}

Related

How i can implement 2 arrays in tableView

`Hello!
I have a tableview and 2 arrays.
When I switch between tabs the tableview reloads. In the first tab, I click on favorites, change the color and add the data to another array. When switching to the second tab, the color does not change. how can i implement this?
MyCell
protocol CellSubclassDelegate: class {
func gestureTapped(cell: StocksCell)
}
class StocksCell: UITableViewCell {
#IBOutlet weak var logoImageView: UIImageView!
#IBOutlet weak var tickerLabel: UILabel!
#IBOutlet weak var favouriteImageView: UIImageView!{ didSet {
let panGesture = UITapGestureRecognizer(target: self, action: #selector(tapToAddFavourite))
favouriteImageView.addGestureRecognizer(panGesture)
favouriteImageView.isUserInteractionEnabled = true
}
}
#IBOutlet weak var companyNameLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBOutlet weak var deltaLabel: UILabel!
var selectedCell = false
weak var delegate: CellSubclassDelegate?
override func awakeFromNib() {
super.awakeFromNib()
}
#objc private func tapToAddFavourite(_ recognizer: UITapGestureRecognizer) {
guard recognizer.state == .ended else { return }
if selectedCell{
favouriteImageView.tintColor = UIColor.lightGray
selectedCell = false
}else{
favouriteImageView.tintColor = UIColor.yellow
selectedCell = true
}
self.delegate?.gestureTapped(cell: self)
}
}
MyController
class StocksViewController: UIViewController, CellSubclassDelegate {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var stocksLabel: UILabel! { didSet {
let tapGestureStocks = UITapGestureRecognizer(target: self, action: #selector(tapToStocks))
stocksLabel.addGestureRecognizer(tapGestureStocks)
stocksLabel.isUserInteractionEnabled = true
}
}
#IBOutlet weak var favouriteLabel: UILabel!{ didSet {
let tapGestureFavourite = UITapGestureRecognizer(target: self, action: #selector(tapToFavourite))
favouriteLabel.addGestureRecognizer(tapGestureFavourite)
favouriteLabel.isUserInteractionEnabled = true
}
}
fileprivate var stocksData = [StocksModel(n: "VNDX", f: "Vandex, LLC", t: "4 764,6 ₽", tt: "+55 ₽ (1,15%)"), StocksModel(n: "DDD", f: "Dandex, LLC", t: "1 764,6 ₽", tt: "+155 ₽ (1,15%)")]
var favouriteData = [StocksModel]()
let privateIdentifire = "StocksCell"
var isStocksSelected = true
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
#objc private func tapToFavourite(_ recognizer: UITapGestureRecognizer) {
guard recognizer.state == .ended else { return }
favouriteLabel.alpha = 1
favouriteLabel.font = favouriteLabel.font.withSize(28)
stocksLabel.alpha = 0.65
stocksLabel.font = stocksLabel.font.withSize(18)
stocksLabel.textAlignment = .center
isStocksSelected = false
tableView.reloadData()
}
#objc private func tapToStocks(_ recognizer: UITapGestureRecognizer) {
guard recognizer.state == .ended else { return }
favouriteLabel.alpha = 0.65
favouriteLabel.font = favouriteLabel.font.withSize(18)
stocksLabel.alpha = 1
stocksLabel.font = stocksLabel.font.withSize(28)
stocksLabel.textAlignment = .left
isStocksSelected = true
tableView.reloadData()
}
}
TABLEVIEW DATASOURCE
extension StocksViewController: UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let result = isStocksSelected ? stocksData.count : favouriteData.count
return result
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: privateIdentifire, for: indexPath) as! StocksCell
cell.delegate = self
if isStocksSelected{
cell.tickerLabel.text = stocksData[indexPath.row].name
cell.companyNameLabel.text = stocksData[indexPath.row].fullname
cell.priceLabel.text = stocksData[indexPath.row].ticker
cell.deltaLabel.text = stocksData[indexPath.row].tq
}else{
cell.tickerLabel.text = favouriteData[indexPath.row].name
cell.companyNameLabel.text = favouriteData[indexPath.row].fullname
cell.priceLabel.text = favouriteData[indexPath.row].ticker
cell.deltaLabel.text = favouriteData[indexPath.row].tq
}
return cell
}
func gestureTapped(cell: StocksCell) {
guard let indexPath = self.tableView.indexPath(for: cell) else {return}
if cell.selectedCell{
let dataStock = stocksData[indexPath.row]
favouriteData.append(dataStock)
}else{
favouriteData.remove(at: indexPath.row)
}
}
}
TABLEVIEW DELEGATE
extension StocksViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 68
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.layer.cornerRadius = 16
}
}
Change the color here:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: privateIdentifire, for: indexPath) as! StocksCell
cell.delegate = self
if isStocksSelected{
favouriteImageView.tintColor = UIColor.lightGray
cell.tickerLabel.text = stocksData[indexPath.row].name
cell.companyNameLabel.text = stocksData[indexPath.row].fullname
cell.priceLabel.text = stocksData[indexPath.row].ticker
cell.deltaLabel.text = stocksData[indexPath.row].tq
}else{
favouriteImageView.tintColor = UIColor.yellow
cell.tickerLabel.text = favouriteData[indexPath.row].name
cell.companyNameLabel.text = favouriteData[indexPath.row].fullname
cell.priceLabel.text = favouriteData[indexPath.row].ticker
cell.deltaLabel.text = favouriteData[indexPath.row].tq
}
return cell
}

How to update UILabel on a button click in UITableViewCell in swift 4 and xcode 9? [duplicate]

This question already has answers here:
Swift - Increment Label with Stepper in TableView Cell
(2 answers)
Closed 4 years ago.
I am building a food ordering app. In which, there are increment and decrement buttons and a UILabel to display quantity. I want to update the quantity label on increment and decrement buttons click. Image of which is attached.
A snippet of My ViewController is
protocol GondolaTableViewCellDelegate: class {
func tableViewCellAddToCart(_ sender: ItemDetailTableViewCell)
func tableViewCellIncrement(_ sender: ItemDetailTableViewCell)
func tableViewCellDecrement(_ sender: ItemDetailTableViewCell)
var tableViewCellQuantity: String { get set }
}
class ItemDetailTableViewCell: UITableViewCell {
//itemTableCell
var quantity = 1
#IBOutlet weak var itemNameLabelCell: UILabel!
#IBOutlet weak var itemDescLabelCell: UILabel!
#IBOutlet weak var itemPriceLabelCell: UILabel!
#IBOutlet weak var itemQuantityLabelCell: UILabel!
#IBOutlet weak var itemDecrementButton: UIButton!
#IBOutlet weak var itemIncrementButton: UIButton!
#IBOutlet weak var addToCartButton: UIButton!
weak var delegate: GondolaTableViewCellDelegate?
#IBAction func addToCartCellButton(_ sender: Any) {
delegate?.tableViewCellAddToCart(self)
//print("Neck, Angel Memory")
}
#IBAction func itemIncrementButtonCell(_ sender: Any) {
delegate?.tableViewCellIncrement(self)
//quantity = quantity+1
//itemQuantityLabelCell.text = "\(quantity)"
}
#IBAction func itemDecrementButtonCell(_ sender: Any) {
delegate?.tableViewCellDecrement(self)
// if quantity == 1 {
// //toastNeck(message: "Min. quantity should be 1")
// }else if quantity >= 2 {
// //quantity = quantity-1
// }
//itemQuantityLabelCell.text = "\(quantity)"
}
}
class AllItemViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, GondolaTableViewCellDelegate {
var tableViewCellQuantity: String = ""
#IBOutlet weak var allItemImageHeader: UIImageView!
#IBOutlet weak var allItemTableView: UITableView!
#IBOutlet weak var allItemLabel: UILabel!
#IBOutlet weak var visualEffect: UIVisualEffectView!
#IBOutlet weak var itemsTableView: UITableView!
#IBOutlet weak var itemDetailLabel: UILabel!
#IBOutlet weak var cartItemLabel: UILabel!
var storeItem = [StoreItem]()
var allItem = [ItemDetaill]()
var quantityArray: [Int] = []
var selectedIndex: Int!
var storeId: String = ""
var storeCatId: String = ""
var storeName: String = ""
var quantity = 1
override func viewDidLoad() {
super.viewDidLoad()
for i in 0 ..< 100 {
quantityArray.append(2)
}
allItemTableView.delegate = self
allItemTableView.dataSource = self
itemsTableView.delegate = self
itemsTableView.dataSource = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return tableView === allItemTableView ? storeItem.count : allItem.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1 //storeItem.count
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 5
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = UIView()
header.backgroundColor = UIColor.white
return header
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return tableView === allItemTableView ? 56 : 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == allItemTableView {
let storeCell = allItemTableView.dequeueReusableCell(withIdentifier: "allItemCell", for: indexPath) as! AllItemTableViewCell
return storeCell
}else {
let itemCell = itemsTableView.dequeueReusableCell(withIdentifier: "itemTableCell", for: indexPath) as! ItemDetailTableViewCell
itemCell.itemNameLabelCell.text = allItem[indexPath.section].item_name
itemCell.itemDescLabelCell.text = allItem[indexPath.section].item_desc
itemCell.itemPriceLabelCell.text = "₹" + allItem[indexPath.section].item_net_price
itemCell.delegate = self
itemCell.addToCartButton.tag = indexPath.section
itemCell.addToCartButton.addTarget(self, action: #selector(addToCarts(_:)), for: .touchUpInside)
itemCell.itemIncrementButton.tag = indexPath.section
itemCell.itemIncrementButton.addTarget(self, action: #selector(increment(_:)), for: .touchUpInside)
itemCell.itemDecrementButton.tag = indexPath.section
itemCell.itemDecrementButton.addTarget(self, action: #selector(decrement(_:)), for: .touchUpInside)
return itemCell
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedIndex = indexPath.section
if tableView == allItemTableView {
}else {
let itemCell = itemsTableView.cellForRow(at: indexPath)
print("Will Work")
}
}
#objc func increment(_ sender: UIButton) {
quantity = quantity + 1
tableViewCellQuantity = "\(quantity)"
//let newQuantity = quantityArray[sender.tag] + 1
//self.quantityArray.replaceSubrange(sender.tag, with: newQuantity)
itemsTableView.reloadData()
}
#objc func decrement(_ sender: UIButton) {
if quantity == 1 {
toastNeck(message: "Min. quantity should be 1")
}else if quantity >= 2 {
quantity = quantity - 1
}
tableViewCellQuantity = "\(quantity)"
itemsTableView.reloadData()
}
#objc func addToCarts(_ sender: UIButton) {
if sender.tag == 0 {
print(storeItem[sender.tag].item_name)
}
}
func tableViewCellAddToCart(_ sender: ItemDetailTableViewCell) {
guard let tappedIndexPath = itemsTableView.indexPath(for: sender) else {
return
}
print(allItem[tappedIndexPath.section].item_name)
}
func tableViewCellIncrement(_ sender: ItemDetailTableViewCell) {
guard let tappedIndexPath = itemsTableView.indexPath(for: sender) else {
return
}
print(allItem[tappedIndexPath.section].created_date)
quantity = quantity + 1
tableViewCellQuantity = "\(quantity)"
//let newQuantity = quantityArray[tappedIndexPath.section] + 1
//self.quantityArray.replaceSubrange(tappedIndexPath.count, with: <#T##Collection#>)
}
func tableViewCellDecrement(_ sender: ItemDetailTableViewCell) {
guard let tappedIndexPath = itemsTableView.indexPath(for: sender) else {
return
}
if quantity == 1 {
toastNeck(message: "Min. quantity should be 1")
}else if quantity >= 2 {
quantity = quantity - 1
}
tableViewCellQuantity = "\(quantity)"
itemsTableView.reloadData()
print(allItem[tappedIndexPath.section].id)
}
func tableViewCellQuantity(_ sender: ItemDetailTableViewCell) {
}
}
However I am able to detect the button clicks through protocols, but unable to update the UILabel.
Also I need to store the added items into data model class and have to be different values of different items, means each item should store diffrent quantities.
There is a similar question here but its not working.
Please let me know if anyone need any more details.
Try this :
#objc func increment(_ sender: UIButton) {
if let cell = sender.superview?.superview as? YourCellClass {
let indexPath = tbl_songsInfo.indexPath(for: cell)
//Do whatever you want
quantity = quantity + 1
tableViewCellQuantity = "\(quantity)"
//let newQuantity = quantityArray[sender.tag] + 1
//self.quantityArray.replaceSubrange(sender.tag, with: newQuantity)
itemsTableView.reloadData()
}
}
check out this link

Updating Label in Cell

I have a TableView which rows contain label and two buttons. What I wanna do is that when a user clicks the first button "Set Name", a pop up view comes up in which he can input text from keyboard. After hitting "Set", pop up view is dismissed and label inside a row containing the clicked button changes to the input text. I set the delegates but I cannot make label to change.
TableView:
import UIKit
class SetGame: UIViewController, UITableViewDelegate, UITableViewDataSource
{
var numOfPlayers = Int()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return numOfPlayers
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
cell.Name.text = "Player \(indexPath.row + 1)"
cell.btn1.tag = indexPath.row
cell.btn2.tag = indexPath.row
return cell
}
override func viewDidLoad()
{
super.viewDidLoad()
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.none
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
#IBAction func setName(sender: UIButton)
{
let thisVC = storyboard?.instantiateViewController(withIdentifier: "SetName") as! SetName
thisVC.delegate = self
present(thisVC, animated: true, completion: nil)
}
#IBAction func setFingerprint(_ sender: UIButton)
{
}
#IBAction func unwindToSetGame(_ segue: UIStoryboardSegue)
{
print("unwinded to SetGame")
}
#IBOutlet weak var tableView: UITableView!
}
extension SetGame: nameDelegate
{
func named(name: String)
{
let indexP = IndexPath(row: 0, section: 0)
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexP) as! TableViewCell
cell.Name.text = "bkjhvghcjhkv"
//wanted to see if it changes first cell. But doesn't work
}
}
TableViewCell Class:
import UIKit
class TableViewCell: UITableViewCell
{
override func awakeFromNib()
{
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
#IBOutlet weak var Name: UILabel!
#IBOutlet weak var btn1: UIButton!
#IBOutlet weak var btn2: UIButton!
}
Pop up View:
import UIKit
protocol nameDelegate
{
func named(name: String)
}
class SetName: UIViewController
{
var delegate: nameDelegate!
override func viewDidLoad()
{
super.viewDidLoad()
window.layer.borderWidth = 1
window.layer.borderColor = UIColor.white.cgColor
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
#IBAction func closePopUp(_ sender: Any)
{
if input.text != ""
{
delegate.named(name: input.text!)
}
dismiss(animated: true, completion: nil)
}
#IBOutlet weak var input: UITextField!
#IBOutlet weak var window: UIView!
}
Replace this
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexP) as! TableViewCell
with
let cell = tableView.cellForRow(at:indexP) as! TableViewCell

How do I increment/decrement a label value with two buttons pressed in tableview Swift [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I need swift code in my ViewController one table view, label, AddButton. In tableview 8 customcells are there, in each cell one label,(-, +) buttons are there. If I press '+' label value must increase while if I press '-' label value decrease, same way happen to each and every cell. Finally, if I press AddButton the total must be added and it displays in a label in viewcontroller Thanks, InAdvance. image
in viewController tableview methods
#IBOutlet var tableviewObj: UITableView!
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return 8
}
public func numberOfSections(in tableView: UITableView) -> Int // Default is 1 if not implemented
{
return 1
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if indexPath.row == 0 {
let cell:firstTableViewCell = tableView.dequeueReusableCell(withIdentifier: "first") as! firstTableViewCell
return cell
}
else if indexPath.row == 1 {
let cell:secondTableViewCell = tableView.dequeueReusableCell(withIdentifier: "second") as! secondTableViewCell
return cell
}
else if indexPath.row == 2 {
let cell:thirdTableViewCell = tableView.dequeueReusableCell(withIdentifier: "third") as! thirdTableViewCell
return cell
}
else if indexPath.row == 3 {
let cell:fourthTableViewCell = tableView.dequeueReusableCell(withIdentifier: "fourth") as! fourthTableViewCell
return cell
}
else if indexPath.row == 4 {
let cell:fifthTableViewCell = tableView.dequeueReusableCell(withIdentifier: "fifth") as! fifthTableViewCell
return cell
}
else if indexPath.row == 5 {
let cell:sixthTableViewCell = tableView.dequeueReusableCell(withIdentifier: "sixth") as! sixthTableViewCell
return cell
}
else if indexPath.row == 6 {
let cell:seventhTableViewCell = tableView.dequeueReusableCell(withIdentifier: "seven") as! seventhTableViewCell
return cell
}else {
let cell:eighthTableViewCell = tableView.dequeueReusableCell(withIdentifier: "eight") as! eighthTableViewCell
return cell
}
}
#IBOutlet var labelObj: UILabel!
#IBAction func Total(_ sender: Any) {
// i need code here
}
class firstTableViewCell: UITableViewCell {
#IBOutlet var labelObj: UILabel!
var cur = 0
var str = ""
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#IBAction func Minus(_ sender: Any) {
if (self.labelObj.text == "1") {
self.labelObj.text = String( 1)
}else
{
cur = Int(labelObj.text!)!
self.labelObj.text = String(cur - 1)
str = self.labelObj.text!
print(str)
}
}
#IBAction func Add(_ sender: Any) {
cur = Int(labelObj.text!)!
self.labelObj.text = String(cur + 1)
str = self.labelObj.text!
print(str)
}
Create a model to hold the value of the label in a cell-like below
struct Product {
var price = 0
}
We need to communicate from cell to viewcontroller so we need a protocol like a below
protocol CartSelection {
func addProductToCart(product : Product, atindex : Int)
}
I have created array to show in tableview. And I will pass the product to cell. So ViewController code is :
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate,CartSelection {
#IBOutlet weak var totalLabel: UILabel!
var productArray = [Product]()
#IBOutlet weak var testTableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for _ in 0...10{
productArray.append(Product(price: 1))
}
testTableview.allowsSelection = false
calculateTotal()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : TestTableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TestTableViewCell
cell.product = productArray[indexPath.row]
cell.valueLabel.text = "\(cell.product.price)"
cell.productIndex = indexPath.row
cell.cartSelectionDelegate = self
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 75
}
#IBAction func addBtnPressed(_ sender: UIButton) {
}
func addProductToCart(product: Product, atindex: Int) {
productArray[atindex] = product
calculateTotal()
}
func calculateTotal()
{
var totalValue = 0
for objProduct in productArray {
totalValue += objProduct.price
}
self.totalLabel.text = "Total \(totalValue)"
}
}
and TableViewCell code like below :
class TestTableViewCell: UITableViewCell {
var product : Product!
private var counterValue = 1
var productIndex = 0
var cartSelectionDelegate: CartSelection?
#IBOutlet weak var valueLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func minusButton(_ sender: UIButton) {
if(counterValue != 1){
counterValue -= 1;
}
self.valueLabel.text = "\(counterValue)"
product.price = counterValue
cartSelectionDelegate?.addProductToCart(product: product, atindex: productIndex)
}
#IBAction func plusButton(_ sender: UIButton){
counterValue += 1;
self.valueLabel.text = "\(counterValue)"
product.price = counterValue
cartSelectionDelegate?.addProductToCart(product: product, atindex: productIndex)
}
}
Output will look like the screenshot below
Initial Stage
After changing value in cell

Stepper on tableview cell (swift)

I put stepper both outlets and action into tableview cell and using protocol delegate to connect it to tableview. When i tapped stepper in first row, stepper value appear normaly in first row but its also appear in some random row. how to fix this?
TableViewCell
protocol ReviewCellDelegate{
func stepperButton(sender: ReviewTableViewCell)
}
class ReviewTableViewCell: UITableViewCell {
#IBOutlet weak var countStepper: UIStepper!
#IBOutlet weak var stepperLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func stepperButtonTapped(sender: UIStepper) {
if delegate != nil {
delegate?.stepperButton(self)
stepperLabel.text = "x \(Int(countStepper.value))"
}
}
ViewController
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
}
})
func stepperButton(sender: ReviewTableViewCell) {
if let indexPath = tableView.indexPathForCell(sender){
print(indexPath)
}
}
Reset the value of stepper while loading your cell. you can reset the cell property values in cell's prepareForReuse method. add the following method in your ReviewTableViewCell class.
override func prepareForReuse()
{
super.prepareForReuse()
countStepper.value = 0.0
}
In tableViewCell VC:
1 - add these field
var cellDelegate: cellProtocol?
var index: IndexPath?
2 - then add this in the delegate:
func onStepperClick(index: Int, sender: UIStepper)
3 - when you have dragged your stepper over as an action use this:
#IBAction func cellStepper(_ sender: UIStepper) {
cellDelegate?.onStepperClick(index: (index?.row)!, sender: sender)
sender.maximumValue = 1 //for incrementing
sender.minimumValue = -1 //for decrementing
//this will make sense later
}
In ViewController
1 - add these to the tableView function that has the cellAtRow variable.
cell.cellDelegate = self
cell.index = indexPath
2 - Use this instead of your stepperButton function
func onStepperClick(index: Int, sender: UIStepper) {
print(index)
if sender.value == 1.0{
//positive side of stepper was pressed
}else if sender.value == -1.0{
//negative side of stepper was pressed
}
sender.value = 0 //resetting to zero so sender.value produce different values on plus and minus
}
Hope this works for you
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
}
NOTE:
1.MY Cell class is just normal..All changes are in viewcontroller class
2.I have taken stepper and over it added ibAddButton with same constraint as ibStepper
class cell: UITableViewCell {
#IBOutlet weak var ibAddButton: UIButton!
#IBOutlet weak var ibStepper: UIStepper!
#IBOutlet weak var ibCount: UILabel!
#IBOutlet weak var ibLbl: UILabel!
}
1.define empty int array [Int]()
var countArray = [Int]()
2.append countArray with all zeros with the number of data u want to populate in tableview
for arr in self.responseArray{
self.countArray.append(0)
}
3.in cell for row at
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! cell
let dict = responseArray[indexPath.row] as? NSDictionary ?? NSDictionary()
cell.ibLbl.text = dict["name"] as? String ?? String()
if countArray[indexPath.row] == 0{
cell.ibAddButton.tag = indexPath.row
cell.ibStepper.isHidden = true
cell.ibAddButton.isHidden = false
cell.ibCount.isHidden = true
cell.ibAddButton.addTarget(self, action: #selector(addPressed(sender:)), for: .touchUpInside)
}else{
cell.ibAddButton.isHidden = true
cell.ibStepper.isHidden = false
cell.ibStepper.tag = indexPath.row
cell.ibCount.isHidden = false
cell.ibCount.text = "\(countArray[indexPath.row])"
cell.ibStepper.addTarget(self, action: #selector(stepperValueChanged(sender:)), for: .valueChanged)}
return cell
}
4.objc functions
#objc func stepperValueChanged(sender : UIStepper){
if sender.stepValue != 0{
countArray[sender.tag] = Int(sender.value)
}
ibTableView.reloadData()
}
#objc func addPressed(sender : UIButton){
countArray[sender.tag] = 1//countArray[sender.tag] + 1
ibTableView.reloadData()
}

Resources