Calling func(didSelectItemAt) while UIcollectionview is on scrolling - swift

Currently I'm using UICollectionView with several cells in it. UICollectionView scrolls horizontally to move between the cells.
My question is : Is there any way to call func(didSelectItemAt) by clicking the cell while its UICollectionView is on scrolling?
Here is gif.
Right after dragging cell to left for scrolling, I click the cell continuously to call func(didSelectItemAt) but it get call only when scrolling is finished. Is it possible to func(didSelectItemAt) to be called instantly right after clicking cell while on scrolling?
Here is my code for collectionView delegate & dataSource.
extension CardViewController : UICollectionViewDelegate,UICollectionViewDataSource {
public func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return cardCount
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = cardCollectionView.dequeueReusableCell(withReuseIdentifier: "card", for: indexPath) as! CardCell
cell.isFront = cellsSelectedStatus[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = cardCollectionView.cellForItem(at: indexPath) as! CardCell
UIView.transition(with: cell, duration: 0.3, options: [.transitionFlipFromLeft,.allowUserInteraction], animations: nil, completion: nil)
cellsSelectedStatus[indexPath.row] = !(cellsSelectedStatus[indexPath.row])
cell.isFront = cellsSelectedStatus[indexPath.row]
print("did select")
}
Collectionview’s dataSource&delegate are called in viewDidLoad.
I know there is allowUserInteraction from UIViewAnimationOptions which allows to click view while its being animated. Is there smilier code for func(didSelectItemAt)?
There’s no networking & UIGestureRecognizers is attached to the cell or collectionview.
So far I've set
isUserInteractionEnabled,
isMultipleTouchEnabled,
allowsMultipleSelection to true for collectionView,
but it still behaves the same.
I’m using Swift3, Xcode9.
Thanks in advance.

Related

Collection view cell, didSelectItem delegate

i have a collectionView with images in cells and by tapping on the item i am deleting it
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
UIView.animate(withDuration: 0.5) {
if let cell = collectionView.cellForItem(at: indexPath) as? CollectionViewCell {
cell.image.center.x += 300 }
} completion: { Bool in
ImageModel.images.remove(at: indexPath.row)
collectionView.deleteItems(at: [indexPath])
}
}
I can delete 1,2,3 cells, but if i scroll it downside sometimes i see on cells that they already moved (like the method UIView.animate was used, but without completion of it) Why is it happens?

CollectionView indexPath.row is not correct? (Inside TableViewCell)

I have a collection view that I want the indexPath.row to. However, whenever I try to print/display the indexPath.row number, it's off. It's a horizontal collection view, so when I try to page right, it goes from: 0, 2, 3, 4, 5 and going backwards it jumps to 5,3,2,1,1,1. It's also varies each time.
Currently the collectionView is inside a tableViewCell. The data is getting loaded off of Firebase database.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return userList.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FeedCollectionViewCell
pageController.currentPage = indexPath.row
pageController.numberOfPages = userList.count
return cell
}
Setting Prefetching enabled to false in storyboard worked.

collectionView cellForItemAtIndexPath called only one time -swift - programmatically

I have a collectionView that I set with this delegate and datasource:
extension CardView : UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let numberOfURLS = cardModel?.urlStrings?.count
return numberOfURLS!
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let videoCell = collectionView.dequeueReusableCell(withReuseIdentifier: "videoCellIdentifier", for: indexPath)
videoCell.backgroundColor = UIColor.random()
return videoCell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return self.bounds.size
}
}
The problem is that the method cellForItemAtIndexpath is called only one time even if the cells returned are more than one.
The collectionView(_:cellForItemAt:) is called only as the cells appear or are about to appear. It won't call it for all of the cells, but only the visible ones (or those about to scroll into view). It is called in a just-in-time manner.
You can also turn on prefetching (which only works if you turn off “Estimate Size” in the collection view’s “Size inspector” IB or manually set the flow layout’s estimatedItemSize to .zero), but that only makes it a tiny bit more “eager” in terms of fetching cells (fetching those that are going to scroll into view a bit sooner than it would otherwise). It will not fetch all of the cells, but just those that the OS determines might possibly scroll into view soon.

UICollectionViewCell is not rounding corners inside UITableView

The problem is that when I have UICollectionView inside UITableViewCell - UICollectionViewCell cornerRadius function not working.
Code is very simple and it was always working for me when playing with UICollectionView.
extension ExploreTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ExploreCollectionViewCell
cell.thumbnail.layer.cornerRadius = 20
cell.thumbnail.clipsToBounds = true
return cell
}
Is it a bug or what? Cannot find any answer all day. Most of the people suggest to use contentView instead of the specific image inside the cell but that's not for me since I want only image to be rounded.
P.S this one works (but I want only image inside the cell to be rounded):
override func awakeFromNib() {
super.awakeFromNib()
self.layer.cornerRadius = 30
self.clipsToBounds = true
}

didDeselectItemAt For UIcollectionView is not called but didSelectItemAt is called?

I am trying to implement a multi selection for UICollectionView. The delegate function didSelectItemAt is called but didDeselectItemAt is NEVER called and I do not know why? I am not even sure how it works. If I click on a cell - didSelectItemAt is called. So if I click once again on the same cell is didDeselectItemAt supposed to be called?
My UIViewController inherits and conforms to all of the following: UICollectionViewDelegate ,UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
viewdidLoad():
collectionView.allowsSelection = true
collectionView.allowsMultipleSelection = true
Delegate functions:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("didSelectItemAt")
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
print("DESELECT")
}
Please see this open issue on Github.
It could be that you have a tap gesture recognizer on a view in the same hierarchy that contains your collection view. Remove the tap gesture and see if that works. This happened to be my issue.
let tap = UITapGestureRecognizer(...) // your tap gesture recognizer
view.addGestureRecognizer(tap) // what you already have
tap.cancelsTouchesInView = false
I'm going to guess that your code is different from what you have shown us, and in that in your real code, you have not given the correct signature for didDeselect. Here's why. Look carefully at the code you have shown:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("didSelectItemAt")
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
print("DESELECT")
}
Now ask yourself: Why did the compiler permit the second func to stand, even though you forgot to say override? I'm guessing it's because it is not an override. There is something wrong with the signature, so it's just a meaningless function that doesn't conform to UICollectionViewDelegate.
Try using code completion to re-enter this function. If all goes well, it will be an override and it will start working.
To illustrate more precisely: This compiles, but the second method will never be called:
class CV : UICollectionViewController {
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("didSelectItemAt")
}
func colectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
print("DESELECT")
}
}
But this doesn't compile, because the signature is correct but we forgot override:
class CV : UICollectionViewController {
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("didSelectItemAt")
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
print("DESELECT")
}
}
But in that second one, if we do say override, it compiles and works.
It works like this:
if collectionView.allowsMultipleSelection = false // default then you have to tap on a different cell in order to deselect the previous one.
if collectionView.allowsMultipleSelection = true // only tapping on the same cell triggers deselect delegate method
I'm not sure if this changed recently, but with iOS13 it seems that simply specifying that a collection view cell is selected when the cell is dequeued is not enough for the collection view to allow you to deselect the cell. You need to also manually tell the collection view to select the cell.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: photoCellIdentifier, for: indexPath) as! YourCell
cell.isSelected = true
if cell.isSelected {
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .left)
}
}
I figured this out because i was able to select and deselect cells, but was not able to deselect a cell that was initially selected.