The issue is in CartViewController - When I click on "Checkout(2)" rightBarButtonItem in the ProductViewController, it shows error in CartviewController's "numberOfRowsInSection" function - Kindly see image & codes below:-
I have been ruminating over for quite some time. Please save my skin.
Detailed link to the problem is here :-
uitableview - swift data not transferred from UIBarButtonItem to another viewcontroller - Stack Overflow[
^]
What I have tried:
1 class ProductViewController -
2
3 import UIKit
4
5 class ProductViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
6 let sections = ["Section A", "Section B"]
7 let rowspersection = [3,1]
8 fileprivate var cart = Cart()
9
10 @IBOutlet weak var tableView: UITableView!
11 override func viewDidLoad() {
12 super.viewDidLoad()
13 tableView.delegate = self
14 tableView.dataSource = self
15 }
16
17 override func viewWillAppear(_ animated: Bool) {
18 super.viewWillAppear(animated)
19
20
21 self.navigationItem.rightBarButtonItem?.isEnabled = false
22 self.navigationItem.rightBarButtonItem?.isEnabled = true
23
24
25
26 cart.updateCart()
27 self.navigationItem.rightBarButtonItem?.title = "Checkout (\(cart.items.count))"
28 tableView.reloadData()
29 }
30
31 override func didReceiveMemoryWarning() {
32 super.didReceiveMemoryWarning()
33
34 }
35 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
36 if segue.identifier == "showCart" {
37 if let cartViewController = segue.destination as? CartViewController {
38 cartViewController.cart = self.cart
39 }
40 }
41 }
42
43 func numberOfSections(in tableView: UITableView) -> Int {
44 return sections.count
45 }
46 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
47 return rowspersection[section]
48 }
49 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
50 let cell = tableView.dequeueReusableCell(withIdentifier: "ProductTableViewCell") as! ProductTableViewCell
51 cell.delegate = self
52
53 var index = indexPath.row
54 if indexPath.section != 0, rowspersection.count > indexPath.section - 1{
55 index += rowspersection[indexPath.section - 1]
56 }
57
58 if index < productarray.count{
59 let data = productarray[index]
60 cell.name?.text = data.name
61 cell.imageView?.image = data.imagename
62 }
63 let product = productarray[indexPath.item]
64 cell.setButton(state: self.cart.contains(product: product))
65 return cell
66 }
67 func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
68 return 44
69 }
70
71 func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
72 switch(section) {
73 case 0:return "Section A"
74 case 1:return "Section B"
75 default :return ""
76
77 }
78 }
79 }
80
81 extension ProductViewController: CartDelegate {
82
83
84 func updateCart(cell: ProductTableViewCell) {
85 guard let indexPath = tableView.indexPath(for: cell) else { return }
86 let product = productarray[indexPath.item]
87
88
89 cart.updateCart(with: product)
90 self.navigationItem.rightBarButtonItem?.title = "Checkout (\(cart.items.count))"
91 }
92 }
The issue is in
CartViewController
- When I click on "Checkout(2)"
rightBarButtonItem
in the
ProductViewController
(see image above), it shows error in
CartviewController
's "
numberOfRowsInSection
" function - see
CartViewController
code below:-
1 import UIKit
2
3 class CartViewController: UIViewController {
4 @IBOutlet weak var tableView: UITableView!
5 @IBOutlet weak var totalView: UIView!
6 @IBOutlet weak var totalLabel: UILabel!
7
8 var cart: Cart? = nil
9 fileprivate let reuseIdentifier = "CartItemCell"
10 override func viewDidLoad() {
11 super.viewDidLoad()
12 tableView.tableFooterView = UIView(frame: .zero)
13 }
14 }
15
16 extension CartViewController: UITableViewDelegate, UITableViewDataSource {
17
18 func numberOfSections(in tableView: UITableView) -> Int {
19
20 return 1
21 }
22 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
23
24 return (cart?.items.count)!
25 }
26
27 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
28 let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! CartItemTableViewCell
29
30 if let cartItem = cart?.items[indexPath.item] {
31 cell.delegate = self as CartItemDelegate
32
33
34
35 cell.quantityLabel.text = String(describing: cartItem.quantity)
36
37 cell.quantity = cartItem.quantity
38
39 }
40 return cell
41 }
42 }
43
44
45 extension CartViewController: CartItemDelegate {
46
47
48 func updateCartItem(cell: CartItemTableViewCell, quantity: Int) {
49 guard let indexPath = tableView.indexPath(for: cell) else { return }
50 guard let cartItem = cart?.items[indexPath.row] else { return }
51
52
53 cartItem.quantity = quantity
54
55
56
57
58
59 }
60 }
My Models -
1 struct Product -
2
3 import UIKit
4
5 struct Product:Equatable {
6 let name : String
7 var quantity : Int
8 var price : Double
9 let imagename: UIImage
10
11
12 }
13 var productarray = [Product(name: "a", quantity: 5, price: 5.0,imagename:#imageLiteral(resourceName: "CakeImage")),
14 Product(name: "b", quantity: 10, price: 10.0, imagename:#imageLiteral(resourceName: "PeasImge")),Product(name: "a", quantity: 5, price: 5.0,imagename:#imageLiteral(resourceName: "vectorlogo")),
15 Product(name: "b", quantity: 10, price: 10.0, imagename:#imageLiteral(resourceName: "blue")),]
16
17 class CartItem -
18
19 import Foundation
20
21 class CartItem {
22 var quantity : Int = 1
23 var product : Product
24
25 init(product: Product) {
26 self.product = product
27 }
28 }
29
30 class Cart -
31
32 import Foundation
33
34 class Cart {
35 var items : [CartItem] = []
36 }
37
38 extension Cart {
39
40
46
47 var totalQuantity : Int {
48 get { return items.reduce(0) { value, item in
49 value + item.quantity
50 }
51 }
52 }
53 func updateCart(with product: Product) {
54 if !self.contains(product: product) {
55 self.add(product: product)
56 } else {
57 self.remove(product: product)
58 }
59 }
60 func updateCart() {
61
62 for item in self.items {
63 if item.quantity == 0 {
64 updateCart(with: item.product)
65 }
66 }
67 }
68
69 func add(product: Product) {
70 let item = items.filter { $0.product == product }
71
72 if item.first != nil {
73 item.first!.quantity += 1
74 } else {
75 items.append(CartItem(product: product))
76 }
77 }
78
79 func remove(product: Product) {
80 guard let index = items.firstIndex(where: { $0.product == product }) else { return}
81 items.remove(at: index)
82 }
83
84
85 func contains(product: Product) -> Bool {
86 let item = items.filter { $0.product == product }
87 return item.first != nil
88 }
89 }
The UITableViewCells -
1 class ProductTableViewCell -
2
3 import UIKit
4 protocol CartDelegate {
5 func updateCart(cell: ProductTableViewCell) }
6 class ProductTableViewCell: UITableViewCell {
7 weak var myParent:ProductViewController?
8 @IBOutlet weak var name: UILabel!
9 @IBOutlet weak var price: UILabel!
10 @IBOutlet weak var imagename: UIImageView!
11 @IBOutlet weak var addToCartButton: UIButton!
12
13 var delegate: CartDelegate?
14
15 override func awakeFromNib() {
16 super.awakeFromNib()
17
18
19 addToCartButton.layer.cornerRadius = 5
20 addToCartButton.clipsToBounds = true
21 }
22
23 func setButton(state: Bool) {
24 addToCartButton.isSelected = state
25 addToCartButton.backgroundColor = (!addToCartButton.isSelected) ? .black : .red
26 }
27
28 @IBAction func addToCart(_ sender: Any) {
29 setButton(state: !addToCartButton.isSelected)
30 self.delegate?.updateCart(cell: self)
31 }
32 }
33
34 class CartItemTableViewCell-
35
36 import UIKit
37
38 protocol CartItemDelegate {
39 func updateCartItem(cell: CartItemTableViewCell, quantity: Int)
40 }
41 class CartItemTableViewCell: UITableViewCell {
42
43 @IBOutlet weak var nameLabel: UILabel!
44 @IBOutlet weak var priceLabel: UILabel!
45
46 @IBOutlet weak var incrementButton: UIButton!
47 @IBOutlet weak var decrementButton: UIButton!
48 @IBOutlet weak var quantityLabel: UILabel!
49
50 var delegate: CartItemDelegate?
51 var quantity: Int = 1
52
53 override func awakeFromNib() {
54 super.awakeFromNib()
55
56
57 incrementButton.layer.cornerRadius = 10
58 incrementButton.clipsToBounds = true
59
60 decrementButton.layer.cornerRadius = 10
61 decrementButton.clipsToBounds = true
62 }
63
64 override func setSelected(_ selected: Bool, animated: Bool) {
65 super.setSelected(selected, animated: animated)
66 }
67
68 @IBAction func updateCartItemQuantity(_ sender: Any) {
69 if (sender as! UIButton).tag == 0 {
70 quantity = quantity + 1
71 } else if quantity > 0 {
72 quantity = quantity - 1
73 }
74
75 decrementButton.isEnabled = quantity > 0
76 decrementButton.backgroundColor = !decrementButton.isEnabled ? .gray : .black
77
78 self.quantityLabel.text = String(describing: quantity)
79 self.delegate?.updateCartItem(cell: self, quantity: quantity)
80 }
81 }
The segues are connected properly. So, I suspect
rightBarButtonItem
i.e. Checkout(2) to another
CartViewcontroller
.
I have been thinking over it for quite some time.
I would sincerely appreciate your assistance. It would mean a lot to me.