Implement delegate in didSelectItemAt - ios

I am using delegate to make a connection between a UICollectionViewCell and a UICollectionViewController. In this connection I want to say, if user clicks on a UIView its super class is changed, I already did it by using gesture.
The only problem is, I think I have to implement this delegation into the didSelectItemAt protocol of UIcollectionView', which I am not sure to how to do it.
For example, first I did it in the cellForItemAt, which was a mistake, buy I could implement easily.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as? ListCell
cell?.selectionDelegate = self // implement the delegate
}
but I don't know how to do the same thing in didSelectItemAt, because I think I should do it here, not in cellForItemAt
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
Thank you so much for your help in advance

Let's say you had your original selection delegate:
protocol SelectionDelegate {
func didSelect(_ cell: ListCell)
}
Then you can easily implement collectionView's didSelect by just calling your selection delegate:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) as? ListCell else { return }
didSelect(cell)
}

Related

Handle moveItem(at:to:) delegate method when using UICollectionViewDiffableDataSource

I need to use moveItem(at:to:) delegate method in order to move my collection view cells.
When I implement the data source delegation methods it's working fine, but I need to set my data source as UICollectionViewDiffableDataSource and in this way the moveItem(at:to:) did not call.
Any solution to handle,
This way it's work when using delegations :
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CustomCell
cell.textLabel.text = "Some value"
return cell
}
override func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
true
}
override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
print("OK")
}
set data source in this way is not work
func setupDataSource() {
dataSource = UICollectionViewDiffableDataSource<Section, Person>(collectionView: collectionView, cellProvider: {
(collectionView: UICollectionView, indexPath: IndexPath, person: Person) -> UICollectionViewCell? in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CustomCell
cell.textLabel.text = "Some text"
return cell
})
}
For custom behavior create a subclass of UICollectionViewDiffableDataSource and override the methods there.

Use of unresolved identifier 'cell' in xcode project

In my match app Xcode project I have an error stating:
Use of unresolved identifier 'cell'.
My Code:
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
}
#IBOutlet weak var collectionView: UICollectionView!
var model = CardModel()
var cardArray:[Card] = []
override func viewDidLoad() {
super.viewDidLoad()
//call the getCards method of the card model
cardArray = model.getCards()
collectionView.delegate = self
collectionView.dataSource = self
}
//mark: -UICollectionView Protocol Methods
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return cardArray.count
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
//get a cardCollectionViewcell object
let cell =
collectionView.dequeueReusableCell(withReuseIdentifier: "CardCell", for: indexPath) as! CardCollectionViewCell
//get card that
let card = cardArray[indexPath.row]
cell.setCard(card)
return
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
_ = collectionView.cellForItem(at: indexPath) as!CardCollectionViewCell
//flip the card
cell.flip() <--------- THIS IS THE ERROR
Once the error is fixed I am supposed to be able run a match app example on the fake iPhone. It would allow me to flip the cards on a click.
I think you forgot to set reusable identifier
I hope this will be resolve your issue.
To access that cell method you have to declare variable
let cell = collectionView.cellForItem(at: indexPath) as!CardCollectionViewCell
First of all you are misusing collectionView:willDisplay:forItemAt. Move everything into collectionView:cellForItemAt, replace return with return cell and delete willDisplay:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CardCell", for: indexPath) as! CardCollectionViewCell
//get card that
let card = cardArray[indexPath.row]
cell.setCard(card)
return cell
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { ... }
The error is pretty clear: You never declared cell is the scope of didSelectItemAt. Change
let cell = collectionView.cellForItem(at: indexPath) as! CardCollectionViewCell

UICollectionViewCell detect tap

I have UICollectionView in ViewController class and I also have a class for UICollectionViewCell.
I have some cells and I need to detect which cell was tapped. How can I detect that?
Use this delegate method
func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath) {
let tappedCell = collectionView.cellForItem(at:indexPath) as! CustomCellClass
print(tappedCell.tag)
}
//
collectionView.delegate = self
//
class CustomVC:UIViewController,UICollectionViewDelegate,UICollectionViewDataSource { --- }
In Swift 5 you can use the didSelectItemAt method:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath) //will return [0, 0] for the first cell, [0, 1] for the second cell etc...
}

UICollectionview - prefetchItemsAt indexPaths - not being called

I'm trying to use prefetching which was introduced in iOS 10. But unable to achieve it.
I do set the delegate and enable the prefetching. But when i set a breakpoint or console log at prefetch, it does not pass through the function ever.
I know on fast scroll, the prefetching is skipped. but even on slowest scroll, its never been called
var dataSource = [IndexPath: Any]()
override func viewDidLoad() {
if #available(iOS 10.0, *) {
mainCollectionView.isPrefetchingEnabled = true
mainCollectionView.prefetchDataSource = self
}
//Other stuffs
}
//This is not being called
func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
print("Prefectch")
for indexPath in indexPaths {
dataSource[indexPath] = fetchDataSource(indexPath)
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! MyCell
cell.dataSource = dataSource[indexPath] ?? fetchDataSource(indexPath)
return cell
}
Call
override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
self.collectionView(collectionView, prefetchItemsAt: [indexPath])
}
To trigger the prefetch, and remove:
collectionViewLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
If you have it.
This was by me the case.

How to display image of selected UICollectioNViewCell in UIView? (Swift 3)

I am new to iOS development, so please bear with me if this is obvious.
I have a UICollectionView on the bottom half of a view controller; it currently displays all photos in my photo library. There is a UIView on the top half of the same view controller.
Q: When I select a UICollectionViewCell (i.e. a photo), how do I display that photo in the UIView on the same view controller?
I imagine I'll have to use didSelectItemAt somehow to save the index path of the selected image in order to display that image in the UIView. (I've included what I have thus far for didSelectItemAt.) How do I refresh the content of the UIView as different photos are selected?
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedVideo = collectionView.cellForItem(at: indexPath)
selectedVideo?.alpha = 0.5
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
let deselectedVideo = collectionView.cellForItem(at: indexPath)
deselectedVideo?.alpha = 1.0
}
put ImageView into your view then make IBOutlet of imageview . you get cell of collectionview , set image of collectionviewcell of imageview image into top imageView
You can try this
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedCell = collectionView.cellForItem(at: indexPath) as! MyCollectionViewCell
yourview.imageView.image = selectedCell.imageView.image
}
From my understanding on the comments you have described earlier, there are 2 ways you can implement.
Using UIViewController, drop a UIView and a UICollectionView.
Using UICollectionViewController, and create a UICollectionReusableView
I'm assuming that you are using the 1st method,
Drop an #IBOutlet for the above UIImageView and name it myImageView for example.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedImage = collectionView.cellForItem(at: indexPath)
myImageView.image = selectedImage.myImageView.image
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedVideo = collectionView.cellForItem(at: indexPath)
view.imageView.image = selectedVideo
}

Resources