I working on cart view controller I tried some of code, it's show like below image.
values updating every row in tableview, if I click on product1 plusbutton count is increase showing 1 .when I click on product2 plusbutton value is showing 2.count is increasing.minus every time minusbutton also working same like that.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell") as! CustomTableViewCell
cell.minusButton.tag = indexPath.row
cell.plusbutton.tag = indexPath.row
cell.minusButton.addTarget(self, action: #selector(minusbuttonClick), for: .touchUpInside)
cell.plusbutton.addTarget(self, action: #selector(plusButtonClick), for: .touchUpInside)
return cell
}
#objc func minusbuttonClick(sender : UIButton)
{
let cell = Tableview.cellForRow(at: NSIndexPath(row: sender.tag, section: 0) as IndexPath) as! CustomTableViewCell
if(count > 0){
count -= 1
}
let myString = String(count)
cell.countLabel.text = myString
if count == 0{
cell.countLabel.text = ""
}
self.Tableview.reloadData()
}
#objc func plusButtonClick(sender : UIButton)
{
let cell = Tableview.cellForRow(at: NSIndexPath(row: sender.tag, section: 0) as IndexPath) as! CustomTableViewCell
count += 1
let myString = String(count)
cell.countLabel.text = myString
self.Tableview.reloadData()
}
I have to show when I click product1 value should be 1, if I click on product2 value as 1
minus also decrease same like that
first thing to do is create a struct to hold your data
struct ProductData {
var count : Int
var name : String
}
and you can use that in your ViewController
var productData : [ProductData] = []
the, of course, you need to add some data - here's a simple set to get started
override func viewDidLoad() {
super.viewDidLoad()
// set up some data.
productData.append(ProductData(count: 0, name: "product 1"))
productData.append(ProductData(count: 0, name: "product 2"))
productData.append(ProductData(count: 0, name: "product 3"))
productData.append(ProductData(count: 0, name: "product 4"))
}
using the delegate model described earlier swift: how to get the indexpath.row when a button in a cell is tapped? update your custom table view cell
protocol TableViewCellCustomDelegate: class {
func buttonTapped(index : Int, delta : Int)
}
class TableViewCellCustom: UITableViewCell {
weak var delegate: TableViewCellCustomDelegate?
#IBOutlet weak var minusButton: UIButton!
#IBOutlet weak var plusButton: UIButton!
#IBOutlet weak var countLabel: UILabel!
#IBOutlet weak var productLabel: UILabel!
override func prepareForReuse() {
super.prepareForReuse()
self.delegate = nil
}
#IBAction func minusButtonClick(_ sender: UIButton) {
delegate?.buttonTapped(index: sender.tag, delta : -1)
}
#IBAction func plusButtonClick(_ sender: UIButton) {
delegate?.buttonTapped(index: sender.tag,delta : +1)
}
}
update the delegate methods in your view controller. I've done it here with a single method to add or delete, but you could split it out if you want to do other things as well.
extension ViewController: TableViewCellCustomDelegate {
func buttonTapped(index: Int, delta : Int)
{
productData[index].count += delta
if productData[index].count < 0
{
productData[index].count = 0
}
tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
}
}
and update your cellForRowAt definition
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! TableViewCellCustom
cell.countLabel.text = "\(productData[indexPath.row].count)"
cell.productLabel.text = productData[indexPath.row].name
cell.minusButton.tag = indexPath.row
cell.plusButton.tag = indexPath.row
cell.delegate = self
return cell
}
Related
I want to get data from tableview after clicking save button .But when user second time change the value then, same value two times append .[
[enter image description here][1]
][2]
protocol ButtonSelect {
func tapStar(indexPath: IndexPath, star: Int)
}
class LeaveDayDetailsCell: UITableViewCell {
#IBOutlet weak var leaveDateLabel: UILabel!
#IBOutlet weak var leaveDateName: UILabel!
#IBOutlet weak var firstButton: UIButton!
#IBOutlet weak var seconButton: UIButton!
#IBOutlet weak var fullButton: UIButton!
var delegate:ButtonSelect?
var indexpath:IndexPath?
#IBAction func bittonPressed(_ sender: UIButton) {
delegate?.tapStar(indexPath: indexpath!, star: sender.tag)
}
}
class DayDetailsController: UIViewController{
#IBAction func buttonPresed(_ sender: UIButton) {
// i want to submit tableview result with radio button value change this place
// example like
//["03/27/2021 + 1", "03/28/2021 + 2"]
// my result
//["03/27/2021 + 1", "03/28/2021 + 2", "03/27/2021 + 3", "03/28/2021 + 2"]
// same value two times
}
}
extension DayDetailsController:UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listDayDetailsData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"LeaveDayDetailsCell",for: indexPath) as! LeaveDayDetailsCell
cell.leaveDateLabel.text = listDayDetailsData[indexPath.row]["BreakDate"] as? String ?? "-"
cell.leaveDateName.text = listDayDetailsData[indexPath.row]["DateName"] as? String ?? "-"
cell.layer.borderColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
cell.layer.borderWidth = 2
dayDetailsTableView.rowHeight = 132.00
cell.delegate = self
cell.indexpath = indexPath
return cell
}
}
extension DayDetailsController:ButtonSelect{
func tapStar(indexPath: IndexPath, star: Int) {
let cell = dayDetailsTableView.cellForRow(at: indexPath) as! LeaveDayDetailsCell
if star == 1{
cell.firstButton.setImage(UIImage(named: "radioFull.png"), for: .normal)
cell.seconButton.setImage(UIImage(named: "radioBlank.png"), for: .normal)
cell.fullButton.setImage(UIImage(named: "radioBlank.png"), for: .normal)
totalvalue = star
}
else if star == 2{
cell.firstButton.setImage(UIImage(named: "radioBlank.png"), for: .normal)
cell.seconButton.setImage(UIImage(named: "radioFull.png"), for: .normal)
cell.fullButton.setImage(UIImage(named: "radioBlank.png"), for: .normal)
totalvalue = star
}
else if star == 3{
cell.firstButton.setImage(UIImage(named: "radioBlank.png"), for: .normal)
cell.seconButton.setImage(UIImage(named: "radioBlank.png"), for: .normal)
cell.fullButton.setImage(UIImage(named: "radioFull.png"), for: .normal)
totalvalue = star
}
answerValue.append("\(listDayDetailsData[indexPath.row]["BreakDate"] as! String) + \(totalvalue)")
print(answerValue,"****answer")
}
}
Keep the star count in your listDayDetailsData and update the value according to the button taps
LeaveDayDetailsCell
class LeaveDayDetailsCell: UITableViewCell {
#IBOutlet weak var leaveDateLabel: UILabel!
#IBOutlet weak var leaveDateName: UILabel!
#IBOutlet weak var firstButton: UIButton!
#IBOutlet weak var seconButton: UIButton!
#IBOutlet weak var fullButton: UIButton!
}
DayDetailsController extension
extension DayDetailsController:UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listDayDetailsData.count
}
#objc func firstButtonPressed(sender: UIButton) {
let index = sender.tag
// Update star value in listDayDetailsData[index]
// Reload single row at index 0
dayDetailsTableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .none)
}
#objc func secondButtonPressed(sender: UIButton) {
let index = sender.tag
// Update star value in listDayDetailsData[index]
// Reload single row at index 0
dayDetailsTableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .none)
}
#objc func fullButtonPressed(sender: UIButton) {
let index = sender.tag
// Update star value in listDayDetailsData[index]
// Reload single row at index 0
dayDetailsTableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .none)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"LeaveDayDetailsCell",for: indexPath) as! LeaveDayDetailsCell
// cell.leaveDateLabel.text = listDayDetailsData[indexPath.row]["BreakDate"] as? String ?? "-"
// cell.leaveDateName.text = listDayDetailsData[indexPath.row]["DateName"] as? String ?? "-"
cell.layer.borderColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
cell.layer.borderWidth = 2
cell.firstButton.tag = indexPath.row
cell.seconButton.tag = indexPath.row
cell.fullButton.tag = indexPath.row
cell.firstButton.addTarget(self, action: #selector(firstButtonPressed(sender:)), for: .touchUpInside)
cell.firstButton.addTarget(self, action: #selector(secondButtonPressed(sender:)), for: .touchUpInside)
cell.firstButton.addTarget(self, action: #selector(fullButtonPressed(sender:)), for: .touchUpInside)
switch listDayDetailsData[indexPath.row]["Star"] as! Int {
case 1:
// Update your cell buttons
break
case 2:
// Update your cell buttons
break
case 3:
// Update your cell buttons
break
default:
// Default case
break
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 132.00
}
}
Pro tip:
It's better to use an Object for keeping your data than a Dictionary
eg
struct DayDetails {
var breakDate: String
var dateName: String
var stars: Int
//....
}
And there are third party libraries available for handling star rating UI as well
https://github.com/evgenyneu/Cosmos
now cell value are dynamically and its look after calling api.
I want to make total of all tickets price at last. I refer this link How do I increment/decrement a label value with two buttons pressed in tableview Swift and make changes in my code but didn't work for me.
struct Product {
var price = 0
}
class TicketBookingVC: UIViewController , UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tblView: UITableView!
#IBOutlet weak var mainTblView: UIView!
var bookingDetails = NSDictionary()
var productArray = [Product]()
var product : Product!
private var counterValue = 1
var productIndex = 0
var counterLbl = UILabel()
#IBOutlet weak var bookBtn: UIButton!
#IBOutlet weak var eventImg: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
tblView.delegate = self
tblView.dataSource = self
for _ in 0...10{
productArray.append(Product(price: 1))
}
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 1
}
else if section == 1{
return 4
}
else{
return 1
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellfirst", for: indexPath)
cell.selectionStyle = .none
return cell
}
else if indexPath.section == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellsecond", for: indexPath)
let mainViewCell = cell.contentView.viewWithTag(2000) as! UIView
let normalView = cell.contentView.viewWithTag(2001) as! UIView
let eventName = cell.contentView.viewWithTag(2003) as! UILabel
let eventPrice = cell.contentView.viewWithTag(2004) as! UILabel
counterLbl = cell.contentView.viewWithTag(2007) as! UILabel
let decrementBtn = cell.contentView.viewWithTag(2005) as! UIButton
let incrementBtn = cell.contentView.viewWithTag(2006) as! UIButton
decrementBtn.addTarget(self, action:#selector(self.decrementbuttonClicked), for: .touchUpInside)
incrementBtn.addTarget(self, action:#selector(self.incrementbuttonClicked), for: .touchUpInside)
product = productArray[indexPath.row]
counterLbl.text = "\(product.price)"
cell.selectionStyle = .none
return cell
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellthird", for: indexPath)
cell.selectionStyle = .none
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 0{
return UITableView.automaticDimension
}
else{
return 80
//return UITableView.automaticDimension
}
}
#objc func decrementbuttonClicked() {
print("Button decrement")
if(counterValue != 1){
counterValue -= 1;
}
self.counterLbl.text = "\(counterValue)"
product.price = counterValue
}
#objc func incrementbuttonClicked() {
counterValue += 1;
self.counterLbl.text = "\(counterValue)"
product.price = counterValue
}
func addProductToCart(product: Product, atindex: Int) {
productArray[atindex] = product
calculateTotal()
}
func calculateTotal()
{
var totalValue = 0
for objProduct in productArray {
totalValue += objProduct.price
}
self.eventPrice.text = "Total \(totalValue)"
}
}
when I increment or decrement value of first cell it reflect in 4th cell. please help. I am new at swift.
This is due to cell reuse. You should set a model for each cell
would love to pass the value postArray[indexpath.row].creatorId when the label inside a tableview cell is tapped so it can be passed onto the next view controller so i can load the profile of that particular creator/user. I used custom cells, so how do i get the creator id based on the location of the label(username) selected.
//custom cell
class PostCell : UITableViewCell
{
#IBOutlet weak var timeAgoLabel: UILabel!
#IBOutlet weak var usernameLabel: UILabel!
#IBOutlet weak var profileImageView: UIImageView!
#IBOutlet weak var postImageView: UIImageView!
#IBOutlet weak var captionLabel: UILabel!
#IBOutlet weak var postStatsLabel: UILabel!
}
//do something when label is tapped
#objc func tapFunction(sender:UITapGestureRecognizer) {
//userClicked = creatorData
print(userClicked)
appDelegate.profileView()
print("tap working")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0{
return 1
}else{
return postsArray.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//var returnCell: UITableViewCell!
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as! statusCell
profilePicture = UserDefaults.standard.object(forKey: "userPic") as? String
if profilePicture != nil {
//load profile picture from library
let urlString = "https://test.com/uploads/profile-picture/"+(profilePicture)!
let profileURL = URL(string: urlString)
cell.statusProfilePic?.downloadedFrom(url: profileURL!)
} else {
print("you have no profile picture set")
}
return cell
} else {
if postsArray[indexPath.row].photos != nil{
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
if postsArray[indexPath.row].comments != nil {
comments = postsArray[indexPath.row].comments?.count
} else {
comments = 0
}
if postsArray[indexPath.row].like_list != nil {
likes = postsArray[indexPath.row].like_list?.count
}else{
likes = 0
}
//assign post id to PostID
postID = postsArray[indexPath.row].post_id
//make username clickable!
let tap = UITapGestureRecognizer(target: self, action: #selector(NewsfeedTableViewController.tapFunction))
cell.usernameLabel.isUserInteractionEnabled = true
cell.usernameLabel.addGestureRecognizer(tap)
cell.usernameLabel.text = postsArray[indexPath.row].fullname
cell.timeAgoLabel.text = postsArray[indexPath.row].data_created
cell.captionLabel.text = postsArray[indexPath.row].content
cell.timeAgoLabel.text = postsArray[indexPath.row].modified
//15 Likes 30 Comments 500 Shares
cell.postStatsLabel.text = "\(likes!) Likes \(comments!) Comments"
//load profile picture from library
let urlString = "https://test.com/uploads/profile-picture/"+(postsArray[indexPath.row].profile_pic_filename)!
let profileURL = URL(string: urlString)
cell.profileImageView.downloadedFrom(url: profileURL!)
//iterate through posts images images array
//load post picture from server library
var postImageName : String?
if postsArray[indexPath.row].photos != nil{
let postImage = postsArray[indexPath.row].photos
for postsImage in postImage!{
postImageName = postsImage.filename!
}
let urlPostImageString = "https://test.com/uploads/post-picture/"+(postImageName)!
let postsImageUrl = URL(string: urlPostImageString)
cell.postImageView.downloadedFrom(url: postsImageUrl!)
} else {
print("Post has no picture")
}
//return cell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "NoImageCell", for: indexPath) as! NoImageTableViewCell
if postsArray[indexPath.row].comments != nil {
comments = postsArray[indexPath.row].comments?.count
} else {
comments = 0
}
if postsArray[indexPath.row].like_list != nil {
likes = postsArray[indexPath.row].like_list?.count
} else {
likes = 0
}
//make username clickable!
let tap = UITapGestureRecognizer(target: self, action: #selector(NewsfeedTableViewController.tapFunction))
cell.noImageUsername.isUserInteractionEnabled = true
cell.noImageUsername.addGestureRecognizer(tap)
cell.noImageUsername.text = postsArray[indexPath.row].fullname
cell.noImageTime.text = postsArray[indexPath.row].data_created
cell.noImagePost.text = postsArray[indexPath.row].content
cell.noImageTime.text = postsArray[indexPath.row].modified
//15 Likes 30 Comments 500 Shares
cell.noImageLikeAndComment.text = "\(likes!) Likes \(comments!) Comments"
//load profile picture from library
let urlString = "https://test.com/uploads/profile-picture/"+(postsArray[indexPath.row].profile_pic_filename)!
let profileURL = URL(string: urlString)
cell.noImageProfilePic.downloadedFrom(url: profileURL!)
return cell
}
}
}
Use this for example.
Implement didSelectRow() method and in it write something like this:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// this method works, when you taped cell. write here code of you need. Next code only example, which set user info to some VC and push it:
let controller = UserController as? UserController
if let controller = controller {
controller.user = users[indexPath.row]
self.navigationController?.pushViewController(controller, animated: true)
}
}
add this to your Cell's class:
func setTap() {
let tap = UITapGestureRecognizer(target: self, action: #selector(tapRecognized))
self.label.addGestureRecognizer(tap)
tap.numberOfTapsRequired = 1
}
#objc func tapRecognized(sender: UITapGestureRecognizer) {
// here your code of tap on label
print("label tapped")
}
Check on storyBoard is your label isUserInteractionEnabled? - set it to true. Inside tapRecodnized() method do what are you need. And you need to call method setTap() in your cell's method, which you call in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell.
Update
Simple example. this code know what are you tapped. if you tap cell, but not label, add code of push some controller, else code of push another controller.
Cell's Class:
class MyTableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel!
var mainController: ViewController?
func setText(text: String) {
setTap()
label.text = text
}
func setTap() {
let tap = UITapGestureRecognizer(target: self, action: #selector(tapRecognized))
self.label.addGestureRecognizer(tap)
tap.numberOfTapsRequired = 1
}
#objc func tapRecognized(sender: UITapGestureRecognizer) {
if let mainController = mainController {
print("label tapped")
mainController.pushSomeVc(cell: self)
}
}
}
Code of main Class:
class ViewController: UIViewController {
#IBOutlet weak var myTableView: UITableView!
var array = ["1", "2", "3", "4", "5", "6"]
override func viewDidLoad() {
super.viewDidLoad()
}
func pushSomeVc(cell: MyTableViewCell) {
let row = myTableView.indexPath(for: cell)?.row
if let row = row {
// write here code of push controller, when label tapped. row property for get some user from array
print("push some vc with \(row)")
}
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCell(withIdentifier: "cell") as? MyTableViewCell
if let cell = cell {
cell.setText(text: array[indexPath.row])
cell.mainController = self
}
return cell ?? UITableViewCell()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
// write here code of push controller with comments
print("cell tapped: \(indexPath.row)")
}
}
I tested this code and it's work perfect
I have a ViewController with a TableView and a TableViewCell containing multiple sections and rows.
I have 2 button "plus" and "minus" and a label "totalLabel" in each row.
How can I get the value displayed in the label for each specific row when the user presses the + or - button?
for now when I run the app and press the + or - buttons only the totalLabel of the section 0/row 0 is working while random values just appear and disappear in the other sections/rows
my tableViewCell code :
import UIKit
protocol CommandeCellDelegate: class {
}
class CommandeCell: UITableViewCell {
weak var delegate : CommandeCellDelegate!
#IBOutlet weak var drinksLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBOutlet weak var totalLabel: UILabel!
#IBOutlet weak var plusButton: UIButton!
#IBOutlet weak var minusButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
here is my code for cellForRowAt :
class MenuViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, CommandeCellDelegate {
var count : Int = 0
var countValue : String!
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CommandeCell", for: indexPath) as! CommandeCell
cell.plusButton.tag = indexPath.section
cell.plusButton.tag = indexPath.row
cell.plusButton.addTarget(self, action: #selector(self.increaseValue), for: .touchUpInside)
cell.minusButton.tag = indexPath.section
cell.minusButton.tag = indexPath.row
cell.minusButton.addTarget(self, action: #selector(self.decreaseValue), for: .touchUpInside)
if indexPath.section == 0 {
let softInfo = softs[indexPath.row]
cell.drinksLabel?.text = softInfo.drinkName
cell.totalLabel?.text = // how to display countValue here?
let HappyHourStatus = partner!.barHHStatus
if case "0" = HappyHourStatus {
cell.priceLabel?.text = softInfo.drinkHHPrice
} else
if case "1" = HappyHourStatus {
cell.priceLabel?.text = softInfo.drinkPrice
}
}
else if indexPath.section == 1 {
let cocktailInfo = cocktails[indexPath.row]
cell.drinksLabel?.text = cocktailInfo.drinkName
cell.totalLabel?.text = // how to display countValue here?
let HappyHourStatus = partner!.barHHStatus
if case "0" = HappyHourStatus {
cell.priceLabel?.text = cocktailInfo.drinkHHPrice
} else
if case "1" = HappyHourStatus {
cell.priceLabel?.text = cocktailInfo.drinkPrice
}
}
return cell
}
and my funcs to increase or decrease the value :
func increaseValue(_ sender: UIButton) -> Int {
count = 1 + count
print(count)
countValue = "\(count)"
let rowToReload = IndexPath(row: sender.tag, section: sender.tag)
let rowsToReload: [Any] = [rowToReload]
tableView.reloadRows(at: rowsToReload as! [IndexPath], with: .automatic)
return count
}
func decreaseValue(_ sender: UIButton) -> Int {
if count == 0 {
print("Count zero")
} else {
count = count - 1
}
countValue = "\(count)"
let rowToReload = IndexPath(row: sender.tag, section: sender.tag)
let rowsToReload: [Any] = [rowToReload]
tableView.reloadRows(at: rowsToReload as! [IndexPath], with: .automatic)
return count
}
I have tried countless solutions but so far none is working - thank you for your help!
So your problem is this code
cell.plusButton.tag = indexPath.section
cell.plusButton.tag = indexPath.row
A tag can only store one value. So you are overriding the section with the row. So it is going to cause all sorts of weirdness. The better solution is to determine what cell you are targeting based on the button itself. Since you know what button was clicked you can convert the location of this button to a point on the table view. And then that point to a a particular index path.
So using your example code you can do something like below:
var softsCount: [Int] = []
var cocktailsCount: [Int] = []
override func viewDidLoad() {
super.viewDidLoad()
softsCount = Array(repeating: 0, count: softs.count) // Fill an array with 0
cocktailsCount = Array(repeating: 0, count: cocktails.count) // Fill an array with 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
if indexPath.section == 0 {
...
cell.totalLabel?.text = "\(softsCount[indexPath.row])"
...
} else if indexPath.section == 1 {
...
cell.totalLabel?.text = "\(cocktailsCount[indexPath.row])"
...
}
...
}
func increaseValue(_ sender: UIButton) {
let pointInTable = sender.convert(sender.bounds.origin, to: tableView)
if let indexPath = self.tableView.indexPathForRow(at: pointInTable), let cell = tableView.cellForRow(at: indexPath) {
if indexPath.section == 0 {
softsCount[indexPath.row] += 1
cell.totalLabel?.text = "\(softsCount[indexPath.row])"
} else if indexPath.section == 1 {
cocktailsCount[indexPath.row] += 1
cell.totalLabel?.text = "\(cocktailsCount[indexPath.row])"
}
}
}
No sure why you are returning count. I am sure this is just a partial implementation. But the button should take care of the entire action including updating the label with the new count. You don't normally return values from button presses.
So updated the example to update the label with the current count. Since I am unable to see what your drinks object I made an assumption that the drinks class has a count parameter that starts at 0. This way each individual drink has a count assigned to it.
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()
}