Post

Replies

Boosts

Views

Activity

Reply to Cell Delegate Method Not Being Called
I ended up resolving this by setting cell.delegate = self in the dataSource handler where I connect the data source to my collection view in EmotionExplorerViewController. // Create diffable data source dataSource = UICollectionViewDiffableDataSource<Section, Item>( collectionView: emotionExplorerCollectionView ) { (collectionView, indexPath, item) -> UICollectionViewCell? in // Return the appropriate cell based on the item type switch item { case .title: return collectionView.dequeueConfiguredReusableCell( using: titleCellRegistration, for: indexPath, item: item ) case .main: let cell = collectionView.dequeueConfiguredReusableCell( using: mainCellRegistration, for: indexPath, item: item ) cell.delegate = self return cell case .filter: return collectionView.dequeueConfiguredReusableCell(using: filterCellRegistration, for: indexPath, item: item) case .skeleton: return collectionView.dequeueConfiguredReusableCell(using: skeletonCellRegistration, for: indexPath, item: item) } } I also reverted to using my old cell registration method since the content configuration API was a bit tricky to set up and customise.
Topic: UI Frameworks SubTopic: UIKit
Jul ’25
Reply to Cell Delegate Method Not Being Called
I have updated the cell registration to use UICollectionViewListCell and the accompanying configuration state API. // View Controller Class: class EmotionExplorerViewController: UIViewController, UINavigationControllerDelegate { override func viewDidLoad() { super.viewDidLoad() emotionExplorerCollectionView.collectionViewLayout = createLayout() configureDataSource() applyInitialSnapshot() emotionExplorerCollectionView.delegate = self geminiResponse = GeminiResponse() getGeminiResponse() } func configureDataSource() { let cellRegistration = UICollectionView.CellRegistration<EmotionExplorerCell, Item> { cell, indexPath, item in var contentConfiguration = cell.defaultContentConfiguration() var backgroundConfiguration = cell.defaultBackgroundConfiguration() switch item { case .main(emotion: let emotion, icon: let iconName, red: let red, green: let green, blue: let blue): print("emotion", emotion) contentConfiguration.text = emotion contentConfiguration.image = UIImage(systemName: iconName)?.withTintColor(.black) backgroundConfiguration.backgroundColorTransformer = UIConfigurationColorTransformer { color in return color.withAlphaComponent(0.10) } backgroundConfiguration.backgroundColor = backgroundConfiguration.backgroundColorTransformer?(UIColor(red: red/255, green: green/255, blue: blue/255, alpha: 1)) cell.contentConfiguration = contentConfiguration cell.backgroundConfiguration = backgroundConfiguration cell.delegate = self case .title, .filter: break case .skeleton: break } } } dataSource = UICollectionViewDiffableDataSource<Section, Item>( collectionView: emotionExplorerCollectionView ) { (collectionView, indexPath, item) -> UICollectionViewCell? in // Return the appropriate cell based on the item type switch item { case .title: return collectionView.dequeueConfiguredReusableCell( using: titleCellRegistration, for: indexPath, item: item ) case .main: return collectionView.dequeueConfiguredReusableCell( using: cellRegistration, for: indexPath, item: item ) case .filter: return collectionView.dequeueConfiguredReusableCell(using: filterCellRegistration, for: indexPath, item: item) case .skeleton: return collectionView.dequeueConfiguredReusableCell(using: skeletonCellRegistration, for: indexPath, item: item) } } } // UICollectionViewListCell protocol EmotionExplorerCellDelegate: AnyObject { func repromptLLMForIconName(_ iconName: String, index: Int, emotion: String, red: CGFloat, green: CGFloat, blue: CGFloat) } class EmotionExplorerCell: UICollectionViewListCell { weak var delegate: EmotionExplorerCellDelegate? var iconImageView: UIImageView! var titleLabel: UILabel! var rowIndex: Int! var emotion: String! var red: CGFloat! var green: CGFloat! var blue: CGFloat! override init(frame: CGRect) { super.init(frame: frame) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
Topic: UI Frameworks SubTopic: UIKit
Jul ’25
Reply to Cell Delegate Method Not Being Called
This is my code: // UI View Controller Class class EmotionExplorerViewController: UIViewController, UINavigationControllerDelegate { func configureDataSource() { // Cell registration for main section let mainCellRegistration = UICollectionView.CellRegistration<EmotionExplorerCell, Item> { cell, indexPath, item in switch item { case .main(emotion: let emotion, icon: let iconName, red: let red, green: let green, blue: let blue): cell.delegate = self cell.index = indexPath.row print("collection view cell,", cell) cell.configure(iconName: iconName, title: emotion, red: red, green: green, blue: blue) case .title(title: _, buttonTitle: _): break case .filter(name: _): break case .skeleton: break } } } // Delegate method implementation extension EmotionExplorerViewController: EmotionExplorerCellDelegate { func repromptLLMForIconName(_ iconName: String, index: Int, emotion: String, red: CGFloat, green: CGFloat, blue: CGFloat) { guard let numberOfTries = geminiResponse?.numberOfTries, numberOfTries < 3 else { return } geminiResponse?.rempromptForIconName(iconName) { [self] emotions, error in if var item = dataSource.itemIdentifier(for: IndexPath(row: index, section: 3)) { var snapshot = dataSource.snapshot(for: .main) if let newEmotion = emotions?.first { var insertItem = Item.main(emotion: emotion, icon: newEmotion.sfSymbolName, red: red, green: green, blue: blue) snapshot.insert([insertItem], after: item) snapshot.delete([item]) dataSource.apply(snapshot, to: .main, animatingDifferences: true) } } } } } // UI Collection View Cell Class protocol EmotionExplorerCellDelegate { func repromptLLMForIconName(_ iconName: String, index: Int, emotion: String, red: CGFloat, green: CGFloat, blue: CGFloat) } class EmotionExplorerCell: UICollectionViewCell { var delegate: EmotionExplorerCellDelegate? var iconImageView: UIImageView! var titleLabel: UILabel! var index: Int! var emotion: String! var red: CGFloat! var green: CGFloat! var blue: CGFloat! override init(frame: CGRect) { super.init(frame: frame) configureCell() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func prepareForReuse() { super.prepareForReuse() iconImageView.image = nil titleLabel.text = nil contentView.backgroundColor = nil } private func configureCell() { iconImageView = UIImageView() iconImageView.contentMode = .scaleAspectFit iconImageView.tintColor = .black iconImageView.translatesAutoresizingMaskIntoConstraints = false titleLabel = UILabel() titleLabel.font = .systemFont(ofSize: 18, weight: .medium) titleLabel.textColor = .black titleLabel.translatesAutoresizingMaskIntoConstraints = false contentView.layer.cornerRadius = 7 contentView.layer.cornerCurve = .continuous contentView.clipsToBounds = true contentView.addSubview(iconImageView) contentView.addSubview(titleLabel) NSLayoutConstraint.activate([ iconImageView.centerXAnchor .constraint(equalTo: contentView.leadingAnchor, constant: 20), iconImageView.centerYAnchor .constraint(equalTo: contentView.centerYAnchor), titleLabel.leadingAnchor .constraint(equalTo: iconImageView.centerXAnchor, constant: 20), titleLabel.centerYAnchor .constraint(equalTo: contentView.centerYAnchor), titleLabel.trailingAnchor .constraint(lessThanOrEqualTo: contentView.trailingAnchor, constant: -16) ]) } func configure(iconName: String, title: String, red: CGFloat, green: CGFloat, blue: CGFloat) { if let image = UIImage(systemName: iconName) { iconImageView.image = image } else { print("delegate", delegate) delegate?.repromptLLMForIconName(iconName, index: index, emotion: emotion, red: red, green: green, blue: blue) } iconImageView.image = UIImage(systemName: iconName) titleLabel.text = title.capitalized let transformer = UIConfigurationColorTransformer.init { color in color.withProminence(.quaternary).withAlphaComponent(0.6) } let color = UIColor( red: red/255, green: green/255, blue: blue/255, alpha: 1 ) contentView.backgroundColor = transformer.callAsFunction(color) } }
Topic: UI Frameworks SubTopic: UIKit
Jul ’25
Reply to Cell Delegate Method Not Being Called
Upon checking if the delegate is nil, the delegate is not nil. However, when I reattempted to run the app I ran into this issue: I am registering the cell using UICollectionView.CellRegistration in my view controller class and assigning cell.delegate = self inside this registration completion handler. My cell has a var delegate: EmotionExplorerCellDelegate? property, and inside the configure(iconName: String, title: String, red: CGFloat, green: CGFloat, blue: CGFloat) method in the cell is where I am calling delegate?.repromptLLMforIconName. Now it appears that my cell is nil inside my cell registration.
Topic: UI Frameworks SubTopic: UIKit
Jul ’25
Reply to Cell Delegate Method Not Being Called
Thanks @Claude31 , per your comments, I have a function which is called repromtLLMForIconName which is in my EmotionExplorerCellDelegate protocol. When I call the method which is repromtLLMForIconName from my cell, this method is not called in my delegate which is my EmotionExplorerViewController. I have not checked that the delegate is not nil.
Topic: UI Frameworks SubTopic: UIKit
Jul ’25
Reply to Collection Reusable View Added Via Storyboard Not Registering with the Collection View
Apologies @BabyJ , I implemented the collectionView.register method which resulted in the cell dequeuing correctly, but my label in my header view was appearing nil which caused the application to crash. So I went back to your original answer and I updated the kind to UICollectionView.elementKindSectionHeader, and this worked, dequeuing the header successfully and supplying the label I added in storyboard in the reusable view. I believe that when implementing a collection reusable view in storyboard, I need to use UICollectionView.elementKindSectionHeader because this returns the object with the views in the storyboard.
Topic: UI Frameworks SubTopic: UIKit
Jul ’25
Reply to Collection Reusable View Added Via Storyboard Not Registering with the Collection View
Thanks @BabyJ. I have updated my code to address the discrepancy which you've noted. My code now looks like this: ` let section = NSCollectionLayoutSection(group: group) let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(37.0)) let header = NSCollectionLayoutBoundarySupplementaryItem( layoutSize: headerSize, elementKind: ElementKind.sectionHeader.rawValue, alignment: .topLeading) section.boundarySupplementaryItems = [header] emotionFiltersDataSource.supplementaryViewProvider = { collectionView, kind, indexPath in guard let headerView = collectionView.dequeueReusableSupplementaryView( ofKind: ElementKind.sectionHeader.rawValue, withReuseIdentifier: "emotionFiltersHeaderReusableView", for: indexPath ) as? EmotionFiltersHeaderView else { fatalError("Could not dequeue header view as EmotionFiltersHeaderView") } let sectionTitle = Section.allCases[indexPath.section].rawValue headerView.sectionTitleLabel.text = sectionTitle return headerView } But I am still seeing the error. I had also selected the Section header accessory in the storyboard, but I've now deselected it when I tried using your suggestion and have gotten the same crash as before.
Topic: UI Frameworks SubTopic: UIKit
Jul ’25