Selecting all the items in UICollectionView iOS, even the cells that are not visible
It is not possible to have all cells selected when using cell reuse.
Due to cell reuse the number of actual cells which exist at any moment is a couple more than the number of cells currently visible.
i.e. 6 cells visible is about 8 cells existing.
You are able to find out how many visible cells there are with
NSArray *visiblePaths = [self.collectionView indexPathsForVisibleItems];
The solution is to have the selected
value stored within the UICollectionView datasource and use that value for when you customise a cell inside cellForItemAtIndexPath
How to select all UICollectionView Cell's and Deselect by button click?
I'm not sure why sometimes you use "indexPath.row" and sometimes "indexPath.item".
Regardless, your function should look something like this
@IBAction func selectAllA(_ sender: Any) {
arraySelectedFilterIndex.removeAll()
arraySelectedFilterData.removeAll()
for (index, element) in self.filterTitles.enumerated() {
arraySelectedFilterIndex.append(IndexPath(item: index, section: 0))
arraySelectedFilterData.append(element)
}
collectionView.reloadData()
print(arraySelectedFilterData)
}
At first you are clearing previous selections to avoid duplicates, you could use a map/dictionary structure to avoid duplicated instead of a list though.
Then for each element you add the index and data to the selected list. Finally reload the data, I kept you the print at the end so you can check it.
Select not visible cell inside a collection
Well after a lot of searching, what works for me is to set a local variable say: selectedCell
, then when I want to show a previous user selected cell, i will just set the variable , and on :
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
if(indexPath.row==selectedCell)
}
I am checking if its already selected and mark it .
I could not find any other clever way of doing so automatically .
UICollectionView - Select all cells doesn't update properly
Your code is a little confused because you are trying to keep track of cell selection state both in an array and in the cell itself.
I would just use a Set<IndexPath>
as it is simpler and more efficient than an array. You can then refer to this set when returning a cell in cellForItemAt:
and you don't need to do anything in willDisplay
.
When you select/deselect all you can just reload the whole collection view and when an individual cell is selected/deselected, just reload that cell.
@objcMembers
class MainViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
@IBOutlet var collectionView: UICollectionView!
@IBOutlet var toolBar: UIToolbar?
@IBOutlet weak var selectButton: UIBarButtonItem!
var selectedCells = Set<IndexPath>()
var isSelectAllActive = false
// MARK: - Classes
override func viewDidLoad() {
super.viewDidLoad()
// Collection view
collectionView!.delegate = self
collectionView!.dataSource = self
collectionView!.allowsMultipleSelection = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
@IBAction func selectButtonTapped(_ sender: Any) {
if isSelectAllActive {
// Deselect all cells
selectedCells.removeAll()
selectButton.title = "Select all"
isSelectAllActive = false
} else {
// Select all cells
for i in 0 ..< collectionView!.numberOfItems(inSection: 0) {
self.selectedCells.insert(IndexPath(item:i, section:0))
}
selectButton.title = "Select none"
isSelectAllActive = true
}
self.collectionView.reloadData()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 50
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: UICollectionViewCell
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CVCell", for: indexPath)
if self.selectedCells.contains(indexPath) {
cell.backgroundColor = .green
} else {
cell.backgroundColor = .white
}
if cell.viewWithTag(1) != nil {
let cellTitle = cell.viewWithTag(1) as! UILabel
cellTitle.text = String(indexPath.row)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("\ndidSelectItemAt: \(indexPath.row)")
if selectedCells.contains(indexPath) {
selectedCells.remove(indexPath)
} else {
selectedCells.insert(indexPath)
}
self.collectionView.deselectItem(at: indexPath, animated: false)
self.collectionView.reloadItems(at: [indexPath])
print("selectedCells: \(selectedCells)")
}
}
UICollectionView - Not displaying cells
Since I didn't find a direct solution to it I've tried to set up a new project and did the same changes and tweaks and surprisingly, this time, everything worked from the beginning. I then copied the storyboard to my old project, deleted all the old files and replaced it with the files from the new project. Everything is working good so far. I have no idea what the actual error was but I'm happy it's working now. Thanks to everyone who had a look at my question!
UICollectionView how to deselect all
Not all of the selected cells may be on screen at the point when you are clearing the selection status, so collectionView.cellForItemAtIndexPath(indexPath)
may return nil. Since you have a force downcast you will get an exception in this case.
You need to modify your code to handle the potential nil
condition but you can also make your code more efficient by using the indexPathsForSelectedItems
property of UICollectionView
let selectedItems = followCollectionView.indexPathsForSelectedItems
for (indexPath in selectedItems) {
followCollectionView.deselectItemAtIndexPath(indexPath, animated:true)
if let cell = followCollectionView.cellForItemAtIndexPath(indexPath) as? FollowCell {
cell.checkImg.hidden = true
}
}
UICollectionView is selecting multiple cell even multiple cell selection is false
You should make use of the "isSelected" method for the collection view cell. The way you are doing it is only selecting the cell there is no way of unselecting it. Also, you will need to unselect the previous selected cell If there are any.
So I recommend using this method:
Firstly,
collectionView.allowsMultipleSelection = false
on the UICollectionViewCell you can override the isSelected method
didSet {
if isSelected {
// Change UI for selected state
radioButton.setImage(#imageLiteral(resourceName: "greenTick"), for: .normal)
} else {
// Chage UI for unselected state
radioButton.setImage(#imageLiteral(resourceName: "radioInactive"), for: .normal)
}
}
Finally when you need to find out the indexpath for the selected item.
guard let selectedIndex = self.collectionView.indexPathsForSelectedItems?.first else { return }
Related Topics
How to Add Action to Uialertview in Swift (iOS 7)
How to Record and Save at 240 Frames Per Second
Why HTML5 Video Doesn't Play in iOS 8 Webapp(Webview)
How Come My Drawing Code Keeps Resulting in Fuzzy Shapes
How to Pair And/Or Bond to Ble on iOS Using Swift Code and an Hm-10 So Data Sent Is Encrypted
How to Convert Cgpoint in Nsvalue in Swift
How to Animate Uilabel's Textcolor Change
Auto Layout How to Hide 1 View in a View with 3 Equal Width Views
Get Xcode 5 to Warn About New API Calls
How to Write a Better Data Access Layer with Realm
Uialertview's Textfield Does Not Show Keyboard in iOS8
Testflight Sdk and iOS Simulator - How to Use
How to Compile Aws Customidentityprovider on Xcode 8 Beta 6
Translate Just 4 Lines of Code from Objective C to Swift (Pointers)
Error | [Ios] File Patterns: the 'Source_Files' Pattern Did Not Match Any File