Повторное использование ячейки вызывает нежелательное поведение при обновлении представления ячейки

#ios #objective-c #uicollectionview #uicollectionviewcell

#iOS #objective-c #uicollectionview #uicollectionviewcell

Вопрос:

Я хочу установить границу для выбранной ячейки, я сохраняю свойство ячейки, представляющее выбранную ячейку, и манипулирую им:

 -(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    NSArray *eyeArray = [self eyesArrayConfigure][indexPath.row];
    if (indexPath.row==5) {
        int r = arc4random() % 6;
        eyeArray = [self eyesArrayConfigure][r];
    }
    [borderedCell.contentView.layer  setBorderWidth:0.0f] ;

    UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
    borderedCell = cell;
    [borderedCell.contentView.layer setBorderColor:self.view.tintColor.CGColor];
    [borderedCell.contentView.layer setBorderWidth:3.0f];

}
  

и cellForView: (Я использую 2 типа идентификаторов ячеек, потому что одна ячейка содержит метку — «Случайная ячейка»:

 -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row ==5) {
        UICollectionViewCell *randomCell =[collectionView
                                           dequeueReusableCellWithReuseIdentifier:@"randomCell"
                                           forIndexPath:indexPath];
        randomCell.backgroundColor = [UIColor purpleColor];
        borderedCell = randomCell;
        [borderedCell.contentView.layer setBorderColor:self.view.tintColor.CGColor];
        [borderedCell.contentView.layer setBorderWidth:3.0f];

        return randomCell;
    }
    UICollectionViewCell *myCell = [collectionView  dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];


    NSArray *eyeArray = [self eyesArrayConfigure][indexPath.row];

    myCell.backgroundView = [[UIImageView alloc] initWithImage:eyeArray[1]];


    return myCell;
}
  

Что я получаю, так это то, что если щелкнуть одну ячейку, все будет хорошо, пока я не прокручу, а затем я получаю странное поведение, когда пара ячеек может быть с границей.

Спасибо за помощь.

Комментарии:

1. Это то, что мы называем «ошибкой повторного использования ячейки».

2. Итак, каков наилучший способ подойти к этому? с «тегированием» ячеек?

3. Используйте модель представления, сейчас я пишу ответ.

4. Я позволю @CrimsonChris закончить свой ответ (он / она дает хорошие ответы). В двух словах, только метод cellForItemAtIndexPath должен когда-либо изменять состояние ячейки. В вашем случае это должно быть сделано на основе состояния выбора, записанного в другом методе выбора. Но где записать это состояние? В модели, конечно. Это «модель представления», на которую ссылается CrimsonChris.

Ответ №1:

Решение заключается в использовании модели представления. Вы уже делаете это для фоновых представлений ваших ячеек. Примените ту же концепцию для границы.

 @interface MyCollectionView ()
@property (nonatomic) NSInteger selectedRow;
@end    

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    //update self.selectedRow and either reload entire collection view or just the currently selected and previously selected.
    self.selectedRow = indexPath.row;
    [collectionView reloadData];
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *myCell = [collectionView  dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
    CGFloat borderWidth = (indexPath.row == self.selectedRow) ? 3.0 : 0.0;
    [myCell.contentView.layer setBorderWidth:borderWidth];
    return myCell;
}
  

Комментарии:

1. хорошо, за исключением того, что ваша проверка на равенство слишком сильна. indexPath не будет глубоко равен self.borderedCellIndexPath (selectedIndexPath — лучшее имя). Вместо этого используйте [indexPath compare: self.borderedCellIndexPath] == NSOrderedSame .

2. вы также можете просто перезагрузить по определенному пути индекса. красивее.

3. @danh Оператору потребуется перезагрузить выбранный путь индекса и ранее выбранный путь индекса.

4. О да, хороший момент. Я думаю, что это все же лучший совет для перезагрузки этих двух.

5. Но как насчет вашей логической ошибки? Я бы проголосовал, но это решение только почти правильное. Он не будет работать как закодированный.