The first thing I do is to set the cell selected.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndex
I think the solution @zeiteisen provided is a way around solution. The actual thing lies in the selection mode. There is nothing to be set the in property cell.selected
.
There are two properties of the UICollectionView
name allowsMultipleSelection
and allowsSelection
.
allowsMultipleSelection
is NO
by default and allowsSelection
is YES
.
If you want to select only one cell then the code @the initialization look like
yourCollectionView.allowsMultipleSelection = NO;
yourCollectionView.allowsSelection = YES; //this is set by default
Then the settings will allow you select only one cell at a time, not less not more. You must have to select at least one cell. The didDeselectItemAtIndexPath
wont be called unless you select another cell. Tapping an already selected UICollectionViewCell
won't make it to Deselect. This is the policy behind the implementation.
If you want to select multiple cell then the code @the initialization should look like the following:
yourCollectionView.allowsMultipleSelection = YES;
yourCollectionView.allowsSelection = YES; //this is set by default
Then the settings will allow to select multiple cell. This settings allow none or multiple UICollectionViewCell
to be selected. Number of cell selected will be
0 <= number_selected_cell <= total_number_of_cell
This is the policy behind the multiple cell selection.
If you are intended to use any of the above you are welcome to use apples api without extra headache, otherwise you got to find a way around to sneak into your goal using your own code or apple's api.
I was having the same issue, if you investigate further you willl see that not only the diddiselect is not called, but the touch itself is not perceived by the cell. What solved for me was to allow for async execution of the selection and set the selecItem manually as well. Inside cellForItemAt.
DispatchQueue.main.async {
cell.isSelected = true
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .init())
}
Use .init() and false on animated if you don't want to see movements. If you don't wrap this with the async block you will see the UI jumping while scrolling.
In my case it was caused by using same logic for
func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool
as for
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool
And when cell was selected shouldHighlightItemAt was returning false - and this prevented me to deselect that cell.
Hope this will save someone's time :)
Add this line to your didSelectItemAtIndexPath method
[collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:nil]
The issue is, that the cell is selected, but the UICollectionView
does not know anything about it. An extra call for the UICollectionView
solves the problem:
[collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
Full code:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
cell.selected = YES;
[collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
return cell;
}
I keep the question to help someone who may face the same problem.
I had the same issue. I pre-selected cells upon table load yet I had to double tap a cell to deselect it. @zeiteisen answer helped me. However, I'm working in Swift 3 so I thought I'd give an answer in Swift.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
if /*Test for Selection*/ {
cell.isSelected = true
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .left)
}
return cell
}