0

Я пытался создать представление коллекции со списком ячеек. И когда пользователь нажимает кнопку, он будет случайным образом выбирать одну из ячеек.Ios10 UICollectionView prefetching enabled вызывает selectItemAtIndexPath ведет себя некорректно

Теперь предположим, что всего 10 ячеек. i.e numberOfItemsInSection Делегат возвращает 10. Контроллер представления является источником данных для коллекцииView. Вид коллекции называется myCollectionView. И это имеет свойство selectedIndexPath

Так ViewController:

@interface ViewController() < UICollectionViewDataSource> 
@property (nonatomic, strong) NSIndexPath * selectedIndexPath; 
@property (strong, nonatomic) IBOutlet UICollectionView *myCollectionView; 
@end 

Вот мой случайный выбор кода в контроллере представления:

-(void)chooseRandom{ 
    NSInteger randomShadeIndex = arc4random_uniform((uint32_t)10); 
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:randomShadeIndex inSection:0]; 
    self.selectedIndexPath = indexPath; 
    [self.myCollectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; 
} 

А вот мой cellForItemAtIndexPath на мой взгляд, контроллер

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

И вот setSelected: метод MyCell:

- (void)setSelected:(BOOL)selected{ 
    [super setSelected:selected]; 

    if (selected){ 
     self.backgroundColor = [UIColor redColor]; 
    } else { 
     self.backgroundColor = [UIColor greenColor]; 
    } 
} 

Так что теперь, когда я называю chooseRandom от кнопки. Если случайная ячейка, которая будет выбрана, не видна (не в текущем экране), то есть высокая вероятность того, что она не будет иметь setSelected:YES, который вызывается во время selectItemAtIndexPath:. (Или он вызывается, но устанавливает ячейку. Вместо этого выбирается NO от YES). Значение результирующего экрана не отображает ни одну ячейку.

И интересно, когда я пробовал прикоснуться к экрану (без выбора какой-либо ячейки). Он будет вызывать setSelected: на ячейку, которую нужно выбрать. Так что, думаю, selectItemAtIndexPath: прослушивается.

И это происходит только тогда, когда prefetching enabled в построителе интерфейса настроен на включение (по умолчанию для ios 10).

И я попытался следующие пути решения, но ни один из них не работает:

  1. Добавить [self.myCollectionView cellForItemAtIndexPath:indexPath].selected = YES; в конце chooseRandom.

  2. Использование scrollToItemAtIndexPath наряду с методом 1 вместо selectItemAtIndexPath:

Я думаю, либо это ошибка или я что-то полностью игнорировать. Я застрял на этом часами и не мог понять, почему. Теперь я думаю, что это скорее всего ошибка для selectItemAtIndexPath с prefetching enabled.

Пожалуйста, помогите мне и скажите, если вы столкнулись с той же проблемой. Благодаря!

EDIT: не уверен, что такой же вопрос. this link has similar issue but with deselect

+0

Попробуйте позвонить scrollToItemAtIndexPath: а следующая строка вызова selectItemAtIndexPath: –

+0

@jayarj Я попробовал это, и это не сработало. Также я думаю, что он должен был прокручиваться в selectItemAtIndexPath. – dknyxh

+0

Когда включена предварительная выборка, метод collectionView (_: cellForItemAt :) в делегате представления коллекции вызывается заранее, когда ячейка требуется. Чтобы избежать несоответствий в визуальном внешнем виде, используйте метод делегата collectionView (_: willDisplay: forItemAt :) для обновления ячейки, чтобы отразить визуальное состояние, такое как выбор. – SPatel

ответ

0

A UICollectionView, точно так же как UITableView, кэширует его ячейки. Это означает, что если у вас есть 100 ячеек, и только 10 из них будут видны, он будет создавать только 10 ячеек и повторно использовать их при прокрутке, устанавливая модель/данные видимых ячеек при прокрутке, повторное использование тех, которые не являются видимый больше (для сохранения памяти).Поэтому причина, по которой вы не можете выбрать ячейку, которая не видна, может быть вызвана тем, что она не была создана.

+0

Спасибо, я понимаю, о чем вы говорите. Но я не думаю, что это проблема. Если я отключу предварительную выборку, тогда проблем нет. Это происходит только тогда, когда я включаю предварительную выборку (предварительная выборка включена по умолчанию в ios10) – dknyxh

0

Пожалуйста, проверьте это, если это поможет вам

Можно скачать образец проекта

https://www.dropbox.com/s/oeo9p1h3e8xfpfj/CollectionView.zip?dl=0?

-(void)chooseRandom{ 
    NSInteger randomShadeIndex = arc4random_uniform((uint32_t)50); 
    NSLog(@"%ld",(long)randomShadeIndex); 
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:randomShadeIndex inSection:0]; 
    self.selectedIndexPath = indexPath; 

    [self.myCollectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:true]; 
    [_myCollectionView reloadData]; 
} 
+0

Спасибо за ответ. Но я не думаю, что ваш ответ решил эту проблему. И на самом деле, я думаю, что ваш на самом деле неверен, поскольку свойство видимых ячеек дает только видимую ячейку, и я хочу выбрать случайную ячейку во всех ячейках. И scrollToItemAtIndexPath уже имеет анимированный набор в true, использование [UIView animateWithDuration] не требуется. – dknyxh

+0

Это не только выбор видимых ячеек, self.selectedIndexPath имеет случайный индекс. При прокрутке к выбранному индексному пути ячейка будет автоматически выбрана. Попробуйте загрузить образец проекта и тест ... он содержит ответ –

+0

Добавьте эти две строки кода ** [self.myCollectionView scrollToItemAtIndexPath: indexPath atScrollPosition: UICollectionViewScrollPositionCenteredVertically animated: true]; [_myCollectionView reloadData]; ** –