Handle collection view interactions in iOS using UICollectionViewDelegate methods with UICollectionViewDiffableDataSource. UICollectionViewDelegate provides callbacks for selection, deselection, and highlight events. You implement these methods to navigate to detail views, enable multi-select sharing, and manage selection state. Diffable Data Source provides itemIdentifier(for:) to retrieve model objects from index paths without direct array indexing.
How to Implement Single Selection for Detail View Navigation
Implement the collectionView(_:didSelectItemAt:) delegate method to respond to cell taps. Use it to navigate to a detail view controller with the selected data.
override func collectionView(
_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath
) {
guard let item = dataSource.itemIdentifier(for: indexPath) else { return }
let detailVC = DetailViewController()
detailVC.item = item
navigationController?.pushViewController(detailVC, animated: true)
}
Use itemIdentifier(for:) on the diffable data source to retrieve the model object for the selected index path. This avoids direct array indexing and stays consistent with the snapshot-based data model.
For storyboard segues, call performSegue(withIdentifier:sender:) inside didSelectItemAt. Override prepare(for:sender:) to pass data to the destination controller.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
guard let indexPath = collectionView.indexPathsForSelectedItems?.first,
let item = dataSource.itemIdentifier(for: indexPath),
let detailVC = segue.destination as? DetailViewController
else { return }
detailVC.item = item
collectionView.deselectItem(at: indexPath, animated: false)
}
}
How to Enable Multiple Selection in UICollectionView
Set allowsMultipleSelection to true on the collection view. This enables taps to select multiple cells simultaneously without deselecting previous selections.
collectionView.allowsMultipleSelection = true
Toggle this property to switch between single-selection navigation mode and multi-selection action mode. Use a bar button item to activate the selection mode.
@IBAction func toggleSelectionMode(_ sender: UIBarButtonItem) {
isSelectionMode.toggle()
collectionView.allowsMultipleSelection = isSelectionMode
sender.title = isSelectionMode ? "Done" : "Select"
}
How to Track Selected Items During Multiple Selection
Maintain an array to track selected items and their visual representations. Update this array in the didSelectItemAt and didDeselectItemAt delegate methods.
var selectedItems: [Item] = []
override func collectionView(
_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath
) {
guard isSelectionMode else { return }
guard let item = dataSource.itemIdentifier(for: indexPath) else { return }
selectedItems.append(item)
}
override func collectionView(
_ collectionView: UICollectionView,
didDeselectItemAt indexPath: IndexPath
) {
guard isSelectionMode else { return }
guard let item = dataSource.itemIdentifier(for: indexPath) else { return }
selectedItems.removeAll { $0.id == item.id }
}
The didDeselectItemAt method is critical for data consistency. Without it, the selectedItems array contains stale entries after users deselect cells.
How to Provide Visual Feedback for Selection
Set the selectedBackgroundView property on UICollectionViewCell to show a visual indicator when selected. Configure this in the cell provider or in the cell's awakeFromNib method.
let selectedView = UIView()
selectedView.backgroundColor = UIColor.systemBlue.withAlphaComponent(0.3)
selectedView.layer.borderColor = UIColor.systemBlue.cgColor
selectedView.layer.borderWidth = 2
selectedView.layer.cornerRadius = 8
cell.selectedBackgroundView = selectedView
UIKit cells automatically apply the selectedBackgroundView when allowsMultipleSelection is true. Configure the backgroundView property separately for normal cell appearance.
How to Share Selected Items with UIActivityViewController
Pass the selected items to UIActivityViewController for sharing. Create snapshots of visible cells to preserve the exact visual appearance.
@IBAction func shareSelected(_ sender: UIBarButtonItem) {
guard !selectedItems.isEmpty else { return }
let snapshots: [UIImage] = selectedItems.compactMap { item in
guard let indexPath = dataSource.indexPath(for: item),
let cell = collectionView.cellForItem(at: indexPath)
else { return nil }
return cell.snapshot
}
let activityVC = UIActivityViewController(
activityItems: snapshots,
applicationActivities: nil
)
present(activityVC, animated: true)
}
Create a UIView extension to capture cell snapshots using UIGraphicsImageRenderer for modern iOS rendering.
extension UIView {
var snapshot: UIImage? {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { context in
layer.render(in: context.cgContext)
}
}
}
How to Handle Cell Highlighting and Visual States
Implement collectionView(_:shouldHighlightItemAt:) and collectionView(_:didHighlightItemAt:) for fine-grained control over highlight behavior.
override func collectionView(
_ collectionView: UICollectionView,
shouldHighlightItemAt indexPath: IndexPath
) -> Bool {
return true
}
override func collectionView(
_ collectionView: UICollectionView,
didHighlightItemAt indexPath: IndexPath
) {
guard let cell = collectionView.cellForItem(at: indexPath) else { return }
UIView.animate(withDuration: 0.1) {
cell.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
}
}
override func collectionView(
_ collectionView: UICollectionView,
didUnhighlightItemAt indexPath: IndexPath
) {
guard let cell = collectionView.cellForItem(at: indexPath) else { return }
UIView.animate(withDuration: 0.1) {
cell.transform = .identity
}
}
The highlight methods provide visual feedback before the selection occurs. Combine them with selection methods for a complete interaction experience.
How to Prevent Navigation During Selection Mode
Override shouldPerformSegue(withIdentifier:sender:) to block segues when the collection view is in selection mode.
override func shouldPerformSegue(
withIdentifier identifier: String,
sender: Any?
) -> Bool {
if identifier == "showDetail" && isSelectionMode {
return false
}
return true
}
This prevents accidental navigation when the user intends to select multiple items.
How to Reset Selection State After Sharing
Clear the selection state and exit selection mode after the sharing operation completes. Use the completionWithItemsHandler on UIActivityViewController.
activityVC.completionWithItemsHandler = { _, _, _, _ in
if let indexPaths = self.collectionView.indexPathsForSelectedItems {
for indexPath in indexPaths {
self.collectionView.deselectItem(at: indexPath, animated: true)
}
}
self.selectedItems.removeAll()
self.isSelectionMode = false
self.collectionView.allowsMultipleSelection = false
self.shareButton.title = "Select"
self.shareButton.style = .plain
}
This ensures the collection view returns to normal navigation mode after sharing completes. Users do not need to manually exit selection mode.
Practical Tips for Collection View Interactions
Use isSelectionMode boolean flags to control behavior. Explicit state management makes code readable and debuggable.
Always remove deselected items from the tracking array. Stale references cause incorrect sharing data or crashes.
Test both single and multiple selection on iPad. The popover presentation for UIActivityViewController requires popoverPresentationController configuration.
Set cell selection appearance in the cell subclass. Configure selectedBackgroundView in awakeFromNib or prepareForReuse for consistent styling.
Use UIGraphicsImageRenderer for snapshot capture. It is the modern replacement for UIGraphicsBeginImageContext on iOS 10 and later.
Summary
This tutorial covered the complete implementation process from setup to working code. You now have a functional implementation that you can extend and customize for your own projects. The same patterns apply to related features in the iOS ecosystem.
Frequently Asked Questions
What iOS version is required? The diffable data source used here requires iOS 13 or later.
What are the prerequisites for this tutorial? You need Xcode installed on a Mac and basic familiarity with Swift programming. No prior experience with the specific framework is required.
Can I use this with SwiftUI instead of UIKit? The article demonstrates the UIKit approach. SwiftUI has its own APIs for similar functionality. You can adapt the concepts, but the implementation details differ between the two frameworks.