Reputation: 93
I am creating my app without a storyboard. I passing data between my 2 controllers using Delegate protocol
protocol CatalogueDelegate {
func transferProduct(product: JSONProduct?)
}
class CatalogueController: UITableViewController{
var catalogueDelegate: CatalogueDelegate!
override func viewDidLoad() {
super.viewDidLoad()
feetchLabelProducts(labelId: 2, qnt: nil)
}
private func feetchLabelProducts(labelId: Int, qnt: Int?) {
getLabelProducts(labelId: labelId, qnt: qnt, completed: {
self.tableView.reloadData()
})
}
private func getLabelProducts(labelId: Int, qnt: Int?, completed: @escaping () -> ()) {
APIService.shared.downloadLabelProducts(labelId: labelId, qnt: qnt) { (products, error) in
if let products = products {
self.productList = products
}
DispatchQueue.main.async {
completed()
}
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productList.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellProductId, for: indexPath) as! ProductCell
cell.product = self.productList[indexPath.row]
return cell
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let product = self.productList[indexPath.row]
catalogueDelegate.transferProduct(product: product)
let productDetailVC = ProductDetailController()
navigationController?.pushViewController(productDetailVC, animated: true)
}
}
I do get data on my ProductDetailController and func transferProduct can print it but I need to update my tableView with this new data but for some reasons self.tableView.reloadData() is not working for me.
import UIKit
class ProductDetailController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let productDetailCell = "productDetailCellId"
var product: JSONProduct?
let tableView: UITableView = {
let tableView = UITableView()
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(ProductDetailCell.self, forCellReuseIdentifier: productDetailCell)
tableView.delegate = self
tableView.dataSource = self
tableView.separatorColor = UIColor.clear
view.addSubview(tableView)
view.backgroundColor = UIColor.white
_ = tableView.anchor(view.topAnchor, left: view.leftAnchor, bottom: buyButton.topAnchor, right: view.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: productDetailCell, for: indexPath) as! ProductDetailCell
if let product = self.product {
print(product.title)
} else {
print("No data!!!")
}
return cell
}
}
extension ProductDetailController: CatalogueDelegate {
func transferProduct(product: JSONProduct?) {
guard let item = product else { return }
self.product = item
self.tableView.reloadData()
}
}
Can you please help me to solve this problem? I can print received data
extension ProductDetailController: CatalogueDelegate {
func transferProduct(product: JSONProduct?) {
guard let item = product else { return }
// I can print new data
print(item)
// But I can not update my tablveView with thith new data
self.product = item
tableView.reloadData()
}
}
I did set up delegate in AppDelegate file like this
let productDetailController = ProductDetailController()
let catalogueController = CatalogueController()
catalogueController.catalogueDelegate = productDetailController
Upvotes: 1
Views: 1030
Reputation: 19737
You forgot to set the data in the cellForRowAt
to the cell:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: productDetailCell, for: indexPath) as! ProductDetailCell
if let product = self.product {
// you have to set that product to the cell
print(product.title)
} else {
print("No data!!!")
}
return cell
}
EDIT
Rewrite didSelectRowAt
in CatalogueController
to the following:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let product = self.productList[indexPath.row]
let productDetailVC = ProductDetailController()
productDetailVC.transferProduct(product: product)
navigationController?.pushViewController(productDetailVC, animated: true)
}
I am not sure where you set the delegate
before, but you are presenting a new productDetailVC
that is not the delegate on which you have called transferProduct()
. If this is your whole setup, you don't need a delegate pattern, all you need is to do this:
let productDetailVC = ProductDetailController()
productDetailVC.transferProduct(product: product)
navigationController?.pushViewController(productDetailVC, animated: true)
EDIT 2
Reason why that happens is simple. You set the delegate
in the AppDelegate
:
let productDetailController = ProductDetailController()
let catalogueController = CatalogueController()
catalogueController.catalogueDelegate = productDetailController
But then here you present another different view controller:
let product = self.productList[indexPath.row]
// this sets a product to the delegate object
catalogueDelegate.transferProduct(product: product)
// but the following two lines present another new view controller,
// not the one that is the delegate!
let productDetailVC = ProductDetailController()
navigationController?.pushViewController(productDetailVC, animated: true)
Upvotes: 1