Reputation: 639
I am a Swift beginner attempting to pass the corresponding name and image of the product contained within a cell of a collection view. I have created a singleton and a data file to simulate pulling this info from the internet. I am struggling to assign the values of the collection view cell to the outlets on the detail view controller. Where am I going wrong? I am struggling to understand how to assign these value correctly. Here are my files:
Collection View File
import UIKit
class ProductVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
}
@IBAction func backButtonPressed(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return DataServices.instance.getProducts().count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProductCell", for: indexPath) as? ProductCell {
let product = DataServices.instance.getProducts()[indexPath.row]
cell.updateView(product: product)
return cell
}
return ProductCell()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ProductDetailVC" {
var productDetailVC = segue.destination as! ProductDetailVC
let cell = sender as! UICollectionViewCell
let indexPath = collectionView.indexPath(for: cell)
let product = DataServices.instance.getProducts()[(indexPath?.row)!]
}
}
}
Product Detail View Controller
import UIKit
class ProductDetailVC: UIViewController {
@IBOutlet weak var productName: UILabel!
@IBOutlet weak var productImageView: UIImageView!
var product: Product?
override func viewDidLoad() {
super.viewDidLoad()
}
func updateView() {
productName.text = product?.name
productImageView.image = UIImage(named: (product?.imageName)!)
}
}
Product Model
import Foundation
struct Product {
private(set) public var name: String
private(set) public var imageName: String
init(name: String, imageName: String) {
self.name = name
self.imageName = imageName
}
}
Data Model
import Foundation
class DataServices {
static var instance = DataServices()
var productIndex = 0
private(set) public var categories = [
Category(imageName: "backpackingBG", title: "BACKPACKING"),
Category(imageName: "campingBG", title: "CAMPING"),
Category(imageName: "divingBG", title: "DIVING"),
Category(imageName: "fishingBG", title: "FISHING"),
Category(imageName: "hikingBG", title: "HIKING"),
Category(imageName: "rvBG", title: "RV LIFE")
]
func getCategories() -> [Category] {
return categories
}
private let products = [
Product(name: "SLEEPING BAG", imageName: "sleepingBag"),
Product(name: "CAMPING STOVE", imageName: "campingStove"),
Product(name: "FOOD COOLER", imageName: "foodCooler"),
Product(name: "PARACORD BRACELET", imageName: "paracordBracelet"),
Product(name: "PUP TENT", imageName: "pupTent"),
Product(name: "TACTICAL KNIFE", imageName: "tacticalKnife")
]
func getProducts() -> [Product] {
return products
}
}
Upvotes: 1
Views: 1174
Reputation: 100503
You must implement
optional func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath)
{
self. performSegue(withIdentifier: "ProductDetailVC", sender: indexPath.row)
}
//
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ProductDetailVC" {
var productDetailVC = segue.destination as! ProductDetailVC
let index = sender as! Int
let product = DataServices.instance.getProducts()[index]
productDetailVC.product = product
}
}
Upvotes: 3
Reputation: 3456
In your ProductDetailVC, the updateView() method is never called. You should call it in viewdidLoad. ;)
class ProductDetailVC: UIViewController {
@IBOutlet weak var productName: UILabel!
@IBOutlet weak var productImageView: UIImageView!
var product: Product?
override func viewDidLoad() {
super.viewDidLoad()
updateView() // <-- This is what you missed!
}
func updateView() {
productName.text = product?.name
productImageView.image = UIImage(named: (product?.imageName)!)
}
}
Also if your segue is never triggered, make sure it is set in the storyboard from a cell template to the ProductDetailVC and that make sure your segue identifier in the storyboard is set to ProductDetailVC (case sensitive).
Finally, in your prepareForSegue method, you are not using your last variable (let product = ...) you should pass it to the productDetailVC .
Cheers,
Upvotes: 1
Reputation: 1805
You have forgot to pass product
,for Pass product
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ProductDetailVC" {
var productDetailVC = segue.destination as! ProductDetailVC
let cell = sender as! UICollectionViewCell
let indexPath = collectionView.indexPath(for: cell)
let product = DataServices.instance.getProducts()[(indexPath?.row)!]
productDetailVC.product = product
}
}
And in ProductDetailVC
for update UI
override func viewDidLoad() {
super.viewDidLoad()
self.updateView()
}
Upvotes: 2