Reputation: 817
I have a CollectionViewController and multiple cells. However when I seem to tap onto one of those cells I would need multiple taps before the didSelectItemAt
would read. My cells are spaced out evenly, at least big enough for them to be tapped on. I only get this problem on a real device and not on the simulator.
Here is my code
class TimeAvailabilityCell:UICollectionViewCell{
private let container:UIView = {
let view = UIView()
view.isUserInteractionEnabled = false
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .white
view.layer.borderWidth = 1
view.layer.borderColor = UIColor.systemBlue.cgColor
view.layer.cornerRadius = 8
return view
}()
public let timeLabel:UILabel = {
let label = UILabel()
label.isUserInteractionEnabled = false
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.font = UIFont(name: "AppleSDGothicNeo-Regular", size: 18)
label.textColor = .systemBlue
return label
}()
override init(frame: CGRect) {
super.init(frame:frame)
self.backgroundColor = .green
self.addSubview(container)
container.widthAnchor.constraint(equalToConstant: 100).isActive = true
container.heightAnchor.constraint(equalToConstant: 50).isActive = true
container.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
container.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
container.addSubview(timeLabel)
timeLabel.centerXAnchor.constraint(equalTo: container.centerXAnchor).isActive = true
timeLabel.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
And this is my CollectionViewController
class TimeSelectServiceController: UICollectionViewController, UICollectionViewDelegateFlowLayout{
var timeAvailableArray = [String]()
var timeTitle = ""
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(red: 245/255, green: 245/255, blue: 245/255, alpha: 1)
setupCollectionView()
}
override func viewDidLayoutSubviews() {
self.updateCollectionView()
}
func setupCollectionView(){
let inset = UIEdgeInsets(top: 0, left: 25, bottom: 80, right: 25)
collectionView.contentInset = inset
self.edgesForExtendedLayout = UIRectEdge.bottom
collectionView.backgroundColor = .white
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(TimeAvailabilityCell.self, forCellWithReuseIdentifier: "cell")
collectionView.register(SectionTitleHeader.self, forSupplementaryViewOfKind:UICollectionView.elementKindSectionHeader, withReuseIdentifier: "SectionTitleHeader")
collectionView.allowsSelection = true
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
timeAvailableArray.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! TimeAvailabilityCell
let model = timeAvailableArray[indexPath.row]
cell.timeLabel.text = model.description
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.collectionView.frame.width, height: 50)
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let reusableview = UICollectionReusableView()
switch kind {
case UICollectionView.elementKindSectionHeader:
//FOR HEADER VIEWS
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "SectionTitleHeader", for: indexPath) as! SectionTitleHeader
headerView.title.text = timeTitle
headerView.seeAll.isHidden = true
headerView.backgroundColor = .white
return headerView
default:
return reusableview
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
if(section == 0){
return CGSize(width: view.frame.width, height: 100)
}
return CGSize(width: view.frame.width, height: 100)
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let model = timeAvailableArray[indexPath.row]
BookServiceDetails.details.serviceDate = timeTitle + " at " + model.description
let viewController = ConfirmAppointmentController()
self.navigationController?.pushViewController(viewController, animated: true)
collectionView.deselectItem(at: indexPath, animated: true)
}
func updateCollectionView () {
DispatchQueue.main.async(execute: {
self.collectionView.reloadData()
})
}
}
EDIT
It seems like the more cells I have the harder it is to click on one.
Upvotes: 0
Views: 530
Reputation: 817
I have no idea how this has anything to do with it but I removed collectionView.dataSource = self
and everything works fine now.
Upvotes: 0
Reputation: 113
In TimeAvailabilityCell
add the sub-views to the contentView
instead of the self
.
Disabling user-interaction on the sub-views should not matter.
From the documentation: "To configure the appearance of your cell, add the views needed to present the data item’s content as subviews to the view in the contentView property. Do not directly add subviews to the cell itself."
override init(frame: CGRect) {
super.init(frame:frame)
self.backgroundColor = .green
contentView.addSubview(container)
container.widthAnchor.constraint(equalToConstant: 100).isActive = true
container.heightAnchor.constraint(equalToConstant: 50).isActive = true
container.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
container.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
container.addSubview(timeLabel)
timeLabel.centerXAnchor.constraint(equalTo: container.centerXAnchor).isActive = true
timeLabel.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
}
This:
override func viewDidLayoutSubviews() {
self.updateCollectionView()
}
func updateCollectionView () {
DispatchQueue.main.async(execute: {
self.collectionView.reloadData()
})
}
Creates an endless loop, calling reloadData
on the collection-view, triggers viewDidLayoutSubviews
. Basically the collection-view is reloading the cells constantly, which causes selecting cell to work poorly.
The following blogs are a good reference on how-to setup and work with collection-views; either with storyboards or programmatically. It should give some more insights in how-to setup and configure your collection-view.
Upvotes: 1