I have written the below code to show collections and products from a store. I have used multiple HList1 component and HList2 component on the screen. The issue is when I fast scroll down the Home screen which contains these HList components, some of them are coming up empty. Also, if I goto another screen and then come back to HList, the cell contents are refreshed, but I haven’t added anything to refresh the screen.
Please help.
import UIKit
enum cellStyle {
case Hlist1
case Hlist2
}
class HList: UITableViewCell, UIComponentProtocol, UISheetPresentationControllerDelegate {
var delegate: UIElementSelectedProtocol?
var cellId = "HListCell1"
var componentLayout: UIComponent?
fileprivate var collections: PageableArray<CollectionModel>!
fileprivate var products: PageableArray<ProductModel>!
var HList2Type : CGSize?
@IBOutlet weak var collectionView: UICollectionView!
var currentCellStyle: cellStyle = .Hlist1
var productQuantity : Int = 1
weak var parentViewController: UIViewController?
override func awakeFromNib() {
super.awakeFromNib()
contentView.backgroundColor = .background1
self.collectionView.dataSource = self
self.collectionView.delegate = self
self.collectionView.showsHorizontalScrollIndicator = false
let nib1 = UINib(nibName: "HListCell1", bundle: nil)
collectionView.register(nib1, forCellWithReuseIdentifier: "HListCell1")
let nib2 = UINib(nibName: "HListCell2", bundle: nil)
collectionView.register(nib2, forCellWithReuseIdentifier: "HListCell2")
NotificationCenter.default.addObserver(self, selector: #selector(handleCustomerLogin), name: Notification.Name("CustomerLoggedIn"), object: nil)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
@objc func handleCustomerLogin() {
updateUI(componentLayout!)
}
deinit {
NotificationCenter.default.removeObserver(self, name: Notification.Name("CustomerLoggedIn"), object: nil)
}
func updateUI(_ layout: UIComponent) {
componentLayout = layout
fetchElementValues() { [weak self] elements in
self?.currentCellStyle = layout.style.contains("HSTYLE2") ? .Hlist2 : .Hlist1
self?.cellId = self?.currentCellStyle == .Hlist2 ? "HListCell2" : "HListCell1"
let clnLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
clnLayout.sectionInset = UIEdgeInsets(top: ThemeLayoutProvider.componetVerticalPadding, left: ThemeLayoutProvider.componetHorizontalPadding, bottom: ThemeLayoutProvider.componetVerticalPadding, right: ThemeLayoutProvider.componetHorizontalPadding)
clnLayout.scrollDirection = .horizontal
clnLayout.minimumLineSpacing = 0
clnLayout.minimumInteritemSpacing = 0
if self?.currentCellStyle == .Hlist2 {
clnLayout.itemSize = ThemeLayoutProvider.hList2Size
} else {
switch self?.componentLayout?.elementType {
case "products":
if AccountController.shared.AddToCartEnabled {
if AccountController.shared.customer != nil {
clnLayout.itemSize = ThemeLayoutProvider.hList1Size(for: .productAddToCart)
} else {
clnLayout.itemSize = ThemeLayoutProvider.hList1Size(for: .product)
}
} else {
clnLayout.itemSize = ThemeLayoutProvider.hList1Size(for: .product)
}
case "collection" :
clnLayout.itemSize = ThemeLayoutProvider.hList1Size(for: .collection)
default:
break
}
}
if let products = self?.products, products.items.count > 0 {
let targetIndexPath = IndexPath(item: 0, section: 0)
self?.collectionView.scrollToItem(at: targetIndexPath, at: .left, animated: false)
}
self?.collectionView.collectionViewLayout = clnLayout
self?.collectionView.reloadData()
}
}
func fetchElementValues(completion: @escaping ([Any]) -> Void) {
switch componentLayout?.elementType {
case "products":
if let ids = componentLayout!.elements?.compactMap({ "gid://shopify/Product/"+($0.dataValue ?? "")}) {
ShopifyClient.sharedInstance().fetchProducts(with: ids) {[weak self] prdcts in
self?.products = prdcts
completion(prdcts!.items)
}
}
case "collection":
if let ids = componentLayout!.elements?.compactMap({ "gid://shopify/Collection/"+($0.dataValue ?? "")}) {
ShopifyClient.sharedInstance().fetchCollections(with: ids) {[weak self] colltns in
self?.collections = colltns
completion(colltns!.items)
}
}
default:
break
}
}
}
extension HList: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch componentLayout?.elementType {
case "products":
return products?.items.count ?? 0
case "collection":
return collections?.items.count ?? 0
default:
return 0
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell : HListCell! = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as? HListCell
cell.cellStyle = currentCellStyle
cell.delegate = self
if componentLayout!.style.contains("HSTYLE2") {
cell.mainView.borderColor = .border
}
let anElement = componentLayout?.elements?[indexPath.row]
cell.imageView.setImageFrom(URL.init(string: anElement?.imageUrl ?? ""), placeholder: .imagePlaceHolderSqure)
switch currentCellStyle {
case .Hlist1:
if componentLayout?.elementType == "products" {
cell.product = products?.items[indexPath.row]
if let titleName = componentLayout?.elements?[indexPath.row] {
cell.nameLable.text = titleName.title
}
cell.circleView.isHidden = false
cell.heartImageView.isHidden = false
cell.subLabel.isHidden = false
if AccountController.shared.AddToCartEnabled {//change in constraints}
else if componentLayout?.elementType == "collection" {
cell.collection = collections.items[indexPath.row]
if let titleName = componentLayout?.elements?[indexPath.row] {
cell.nameLable.text = titleName.title
}
cell.circleView.isHidden = true
cell.heartImageView.isHidden = true
cell.subLabel.isHidden = true
cell.addToCart.isHidden = true
cell.productDescription.isHidden = true
cell.nameLable.isHidden = false
cell.nameLable.numberOfLines = 2
NSLayoutConstraint.activate([
cell.nameLable.topAnchor.constraint(equalTo: cell.imageView.bottomAnchor, constant: 5),
cell.addToCart.heightAnchor.constraint(equalToConstant: 0),
cell.nameLable.heightAnchor.constraint(equalToConstant: 31),
cell.productDescription.heightAnchor.constraint(equalToConstant: 0),
cell.subLabel.heightAnchor.constraint(equalToConstant: 0)
])
}
case .Hlist2:
if componentLayout?.elementType == "products" {
cell.product = products?.items[indexPath.row]
if let titleName = componentLayout?.elements?[indexPath.row] {
cell.nameLable.text = titleName.title
}
cell.circleView.isHidden = false
cell.heartImageView.isHidden = false
cell.subLabel.isHidden = false
if AccountController.shared.AddToCartEnabled {
// change in constraints
}
else if componentLayout?.elementType == "collection" {
cell.collection = collections.items[indexPath.row]
if let titleName = componentLayout?.elements?[indexPath.row] {
cell.nameLable.text = titleName.title
}
cell.circleView.isHidden = true
cell.heartImageView.isHidden = true
cell.subLabel.isHidden = true
cell.productDescription.isHidden = true
cell.addToCart.isHidden = true
cell.productNameTop.constant = 30
cell.nameLable.numberOfLines = 2
}
}
return cell
}
extension HList : DismissVariantView {
func didDismissToCart() {}
func didDimissToCheckout(item: [CartItem]) {}
func didDismissToProductDetail() {}
func didDismissToProductList(product: ProductModel, selectedVariant: VariantModel) {
if let indexPath = indexPath(for: product) {
// Reload the cell at the indexPath
collectionView.reloadItems(at: [indexPath])
// Check if the product is in the cart
if CartController.shared.cartContainsProduct(product) {
// Update the "Add to Cart" button title
if let cell = collectionView.cellForItem(at: indexPath) as? HListCell {
cell.addToCart.setTitle("Go To Cart", for: .normal)
cell.isVariantInCart = true
}
} else {
// Update the "Add to Cart" button title
if let cell = collectionView.cellForItem(at: indexPath) as? HListCell {
cell.addToCart.setTitle("Add to Cart", for: .normal)
cell.isVariantInCart = false
}
}
}
}
}
extension HList {
func indexPath(for product: ProductModel) -> IndexPath? {
guard let products = products else { return nil }
if let index = products.items.firstIndex(of: product) {
return IndexPath(item: index, section: 0)
}
return nil
}
}
I’ve been trying to figure out what is causing the issue and saw some solutions that it associated with the dequeuing of the cell, so I have set the name, image etc to nil but that doesnt seem to work.