Swift: UICollectionView selecting cell indexPath issues
(NOTE: I updated this for Swift 4 and more modern practices.)
I stick to UIView
objects as much as possible.
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) else { return }
performSegue(withIdentifier: "showDetail", sender: cell)
}
Then in prepare(for:sender:)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier {
case "showDetail":
guard let indexPath = (sender as? UIView)?.findCollectionViewIndexPath() else { return }
guard let detailViewController = segue.destination as? DetailViewController else { return }
detailViewController.selectedImageName = cellImages[indexPath.row]
detailViewController.selectedLabel = cellLabels[indexPath.row]
default: return
}
}
I used an extension I created a while ago findCollectionViewIndexPath()
extension UIView {
func findCollectionView() -> UICollectionView? {
if let collectionView = self as? UICollectionView {
return collectionView
} else {
return superview?.findCollectionView()
}
}
func findCollectionViewCell() -> UICollectionViewCell? {
if let cell = self as? UICollectionViewCell {
return cell
} else {
return superview?.findCollectionViewCell()
}
}
func findCollectionViewIndexPath() -> IndexPath? {
guard let cell = findCollectionViewCell(), let collectionView = cell.findCollectionView() else { return nil }
return collectionView.indexPath(for: cell)
}
}
I have a suspicion that you have a segue in the storyboard already and don't need func collectionView(, didSelectItemAtIndexPath:)
, but either way, the prepare segue should work.
UICollectionView issue with Select/Deselect cell
As I understand, you want your collectionView
can only select 1 cell at a time and if selected cell is clicked again, it will be deselected. If I'm misunderstanding anything, please tell me.
First
- You shouldn't change
textColor
ofday
indidSelectItemAtIndexPath
anddidDeselectItemAtIndexPath
methods. Because when you scrollcollectionView
, cells will be reused and color ofday
will be wrong for some cells. To resolve it, using property selected of
UICollectionViewCell
.SmartCalendarDayCell.m
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
if (selected) {
self.day.textColor = [UIColor colorWithHexString:@"#D97E66" setAlpha:1];
} else {
self.day.textColor = [UIColor lightGrayColor];
}
}
Second
To deselect selected cell, you should check and do it on collectionView:shouldSelectItemAtIndexPath: method.
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if ([collectionView.indexPathsForSelectedItems containsObject:indexPath]) {
[collectionView deselectItemAtIndexPath:indexPath animated:NO];
return NO;
}
return YES;
}
For more detail, you can check my demo repo here.
Why after selecting cell programmatically - cell is not interaction?
You need to call selectItem
like this
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(with: FAFavouriteCategoryCell.self, for: indexPath)!
let currentCategory = categories[indexPath.row]
if selectedCategories.contains(currentCategory.categoryID) {
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .left) //Add this line
cell.isSelected = true
} else {
collectionView.deselectItem(at: indexPath, animated: false)
cell.isSelected = false
}
cell.configCell(category: currentCategory)
return cell
}
UICollectionView selected cells issue
I have also worked on same things, I have following solution for that.
You need to create array of indexPath which will store selected indexPath.
var arrSelectedIndexPath = [IndexPath]()
In cellForRowAtItem
method add following code which will check if arrSelectedIndexPath contains indexPath then display selected active background else display inactive background.
if arrSelectedIndexPath.contains(indexPath) {
cell?.backgroundView = collectionActive
} else {
cell?.backgroundView = collectionInactive
}
In didSelect
method you need to add following code which also same as above logic, but just add or remove indexPath.
if arrSelectedIndexPath.contains(indexPath) {
cell?.backgroundView = collectionInactive
arrSelectedIndexPath.remove(at: arrSelectedIndexPath.index(of: indexPath)!)
} else {
cell?.backgroundView = collectionInactive
arrSelectedIndexPath.append(indexPath)
}
I hope this solution work for you.
Stored selected indexPath of UICollectionView inside UITableView
This will only work based on the assumption that both your parent table view and child collection views both are not using multiple sections with multiple rows and you only need to store one value for each to represent where an item is located in each respective view.
If I am understanding correctly, you have a collection view for each table view cell. You are storing the selection of each collection view, but you need to also know the position of the collection view in the parent table? A way to do this would be to add a property to your UICollectionView
class or use the tag
property and set it corresponding section it is positioned in the parent table. Then when you save the selected IndexPath
, you can set the section
to be that collection view's property you created(or tag
in the example) so that each selected indexPath.section
represents the table view section
, and the indexPath.row
represents the collection view's row.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//...
let collectionView = UICollectionView()
collectionView.tag = indexPath.section
//...
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
indexPath.section = collectionView.tag
let strData = itemFilter[indexPath.section].value[indexPath.item]
//...
}
Basically each selected index path you save will correspond to the following:
indexPath.section
= table view sectionindexPath.row
= collection view row
IndexPath(row: 5, section: 9)
would correlate to:
--table view cell at IndexPath(row: 0, section: 9)
.
----collection view cell at IndexPath(row: 5, section: 0)
Edit: This is how you can use the saved index paths in your current code
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//...
let tempIndexPath = IndexPath(row: indexPath.row, section: collectionView.tag)
if arrSelectedIndex.contains(tempIndexPath) {
//...
} else {
//...
}
//...
}
Selecting cell in 1 Collection View to change second Collection View properties (Xcode)
Declare a var:
class ViewController:
var newColor : UIColor?
Change this:
if cell.isSelected {
cell2.iconimage.backgroundColor = cell.backgroundColor
}
for this:
if cell.isSelected {
newColor = cell.backgroundColor
iconView.reloadData()
}
in
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
put this
if newColor != nil { // maybe a better test here, if cell was selected
cell2.iconimage.backgroundColor = newColor
}
before
return cell2
Related Topics
How to Add "%" to Data in iOS-Chart
How to Fix Error: This Class Is Not Key Value Coding-Compliant for the Key Tableview.'
Swiftui: Detect Finger Position on MAC Trackpad
Swift - Take Nil as Argument in Generic Function with Optional Argument
How to Call Initializer for Subclass of Generic Type
Using Cocoa Nssavepanel in Sandbox Causes Assertion Failure
How to Create a Hud on Top of My Scenekit.Scene
Terminate Subprocesses of MACos Command Line Tool in Swift
Swift - Initialize View Controller from Storyboard by Overriding Init
Change What Print(Object) Displays in Swift 2.0
Nsuserdefaults in Swift - Implementing Type Safety
Swiftui: How to Draw Filled and Stroked Shape
How to Launch an External Process
Catch Objective-C Exception in Swift
How to Save Cgimage to Data in Swift
iOS 10 App Crashes When Trying to Save Image to Photo Library