web-dev-qa-db-fra.com

UICollectionView - didDeselectItemAtIndexPath non appelé si la cellule est sélectionnée

La première chose que je fais est de définir la cellule sélectionnée.

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
    cell.selected = YES;
    return cell;
}

Et la cellule est sélectionnée avec succès ... Si l'utilisateur touche la cellule sélectionnée, la cellule doit être désélectionnée et les délégués appelés. Mais cela n'arrive jamais. 

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

Je sais que les délégués ne sont pas appelés si je configure la sélection par programme. Le délégué et la source de données sont définis.

Cependant, ce délégué s'appelle:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    return YES;
}

Si je supprime le cell.selected = YES que tout fonctionne. Y a-t-il quelqu'un qui peut m'expliquer ce comportement? 

30
zeiteisen

Le problème est que la cellule est sélectionnée mais que UICollectionView n'en sait rien. Un appel supplémentaire pour la UICollectionView résout le problème:

[collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone]; 

Code complet:

- (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;
}

Je garde la question pour aider quelqu'un qui pourrait être confronté au même problème.

56
zeiteisen

Je pense que la solution fournie par @zeiteisen est un moyen de contourner la solution. La vraie chose réside dans le mode de sélection. Il n'y a rien à définir dans la propriété cell.selected

Il existe deux propriétés de UICollectionView name allowsMultipleSelection et allowsSelection

allowsMultipleSelection est NO par défaut et allowsSelection est YES

Si vous souhaitez sélectionner une seule cellule, le code @ l'initialisation se présente comme suit:

yourCollectionView.allowsMultipleSelection = NO;
yourCollectionView.allowsSelection = YES; //this is set by default

Ensuite, les paramètres vous permettront de sélectionner une seule cellule à la fois, pas moins, pas plus. Vous devez sélectionner au moins une cellule. La didDeselectItemAtIndexPath ne sera pas appelée à moins que vous ne sélectionniez une autre cellule. Taper sur une UICollectionViewCell déjà sélectionnée ne le fera pas sur Désélectionner. C'est la politique derrière la mise en œuvre.

Si vous souhaitez sélectionner plusieurs cellules, le code @ l'initialisation doit ressembler à ceci:

yourCollectionView.allowsMultipleSelection = YES;
yourCollectionView.allowsSelection = YES; //this is set by default

Ensuite, les paramètres permettront de sélectionner plusieurs cellules. Ces paramètres ne permettent à aucun ou à plusieurs UICollectionViewCell d'être sélectionné. Le nombre de cellules sélectionnées sera 

0 <= number_selected_cell <= total_number_of_cell

C'est la politique derrière la sélection de cellules multiples. 

Si vous avez l’intention d’utiliser l’un des éléments ci-dessus, vous pouvez utiliser l’API Apple sans mal de tête, sinon vous devez trouver un moyen de vous faufiler dans votre objectif en utilisant votre propre code ou l’API d’Apple.

23
Ratul Sharker

J'ai eu le même problème. J'ai présélectionné des cellules lors du chargement de la table, mais je devais appuyer deux fois sur une cellule pour la désélectionner. @zeiteisen répondre m'a aidé. Cependant, je travaille dans Swift 3 et j’ai donc pensé donner une réponse dans 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
}
6
Meagan S.

Ajouter cette ligne à votre méthode didSelectItemAtIndexPath

[collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:nil]
1
Nupur Sharma

Dans mon cas, cela a été causé en utilisant la même logique pour

func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool

pour ce qui est de

func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool

Et quand la cellule a été sélectionnée devraitHighlightItemAt retournait faux - et cela m'a empêché de désélectionner cette cellule.

J'espère que cela fera gagner du temps à quelqu'un :)

0
mra214

Recharger la cellule était une solution pour moi. Ce dont j'avais besoin, c'était de changer d'image en cellule pendant un bref instant. J'assigne image à imageView dans cellForItemAtIndexPath et lorsque l'utilisateur touche la cellule, je change d'image et lance mycode, puis recharge la cellule.

 func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
        let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MenuCollectionViewCell
        cell.backgroundImageView.image = UIImage(named: "selected")
        // handle tap events
        collectionView.reloadItemsAtIndexPaths([indexPath])
    }

J'espère que ça aide quelqu'un.

0
Yasin Nazlıcan