it-roy-ru.com

UICollectionView - didDeselectItemAtIndexPath не вызывается, если выбрана ячейка

Первое, что я делаю, это устанавливаю выбранную ячейку.

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

И ячейка успешно выбрана . Если пользователь касается выбранной ячейки, то следует отменить выбор ячейки и вызвать делегатов. Но этого никогда не случится. 

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

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

Я знаю, что делегатов не вызывают, если я устанавливаю выбор программно. Делегат и источник данных установлены.

Тем не менее, этот делегат вызывается:

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

Если я удаляю cell.selected = YES, тогда все работает. Есть ли кто-нибудь, кто может мне объяснить это поведение? 

30
zeiteisen

Проблема в том, что ячейка выбрана, но UICollectionView ничего о ней не знает. Дополнительный вызов для UICollectionView решает проблему:

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

Полный код:

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

Я держу вопрос, чтобы помочь кому-то, кто может столкнуться с той же проблемой.

56
zeiteisen

Я думаю, что решение @zeiteisen - это обходной путь. Реальная вещь лежит в режиме выбора. В свойстве cell.selected нечего устанавливать. 

Существует два свойства UICollectionView name allowsMultipleSelection и allowsSelection

allowsMultipleSelection по умолчанию является NO, а allowsSelection - YES

Если вы хотите выбрать только одну ячейку, то код @ инициализация выглядит так

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

Тогда настройки позволят вам выбрать только одну ячейку за раз, не меньше, а не больше. Вы должны выбрать хотя бы одну ячейку. didDeselectItemAtIndexPath не будет вызываться, если вы не выберете другую ячейку. Нажатие на уже выбранную переменную UICollectionViewCell не приведет к отмене выбора. Это политика реализации.

Если вы хотите выбрать несколько ячеек, то код @ инициализация должен выглядеть следующим образом:

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

Тогда настройки позволят выбрать несколько ячеек. Эти настройки позволяют выбрать один или несколько UICollectionViewCell. Номер выбранной ячейки будет 

0 <= number_selected_cell <= total_number_of_cell

Это политика выбора нескольких ячеек. 

Если вы намереваетесь использовать что-либо из вышеперечисленного, вы можете использовать API-интерфейсы яблок без дополнительной головной боли, в противном случае вам нужно найти способ проникнуть в вашу цель, используя собственный код или API-интерфейс Apple.

23
Ratul Sharker

Я была такая же проблема. Я предварительно выбрал ячейки при загрузке таблицы, но мне пришлось дважды нажать ячейку, чтобы отменить ее выбор. Ответ @zeiteisen помог мне. Тем не менее, я работаю в Swift 3, поэтому я решил дать ответ в 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.

Добавьте эту строку в ваш метод didSelectItemAtIndexPath

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

В моем случае это было вызвано использованием той же логики для

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

что касается

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

И когда ячейка была выбрана, должен HighlightItemAt возвращал false - и это помешало мне отменить выбор этой ячейки.

Надеюсь, это сэкономит кому-то время :)

0
mra214

Перезагрузка камеры была решением для меня. Что мне нужно, так это на короткое время поменять изображение в камере Я назначаю изображение для imageView в cellForItemAtIndexPath, и когда пользователь касается ячейки, я меняю изображение и запускаю mycode, затем перезагружаю ячейку.

 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])
    }

Надеюсь, это поможет кому-то.

0
Yasin Nazlıcan