Ячейки UICollectionView остаются выделенными после перезагрузки

У меня есть UICollectionView с ярлыками внутри ячеек, которые автоматически меняются автоматически. Когда это обновление запускается, я вызываю reloadData в UICollectionView, и я установил ячейки для изменения цвета фона на [UICollectionViewCell setHighlighted:].

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

Я заметил, что dequeueReusableCellWithReuseIdentifier:forIndexPath: вызывает setHighlighted на ячейках после reloadData.

Я также попробовал reloadSections: вместо reloadData, это исправляет проблему того, что ячейки "застревают", но вызывает угасание и появление в ячейках когда-либо их вызываемых.

Размещение вызовов внутри performBatchUpdates: также не устраняет проблему.

Ответ 1

Внутри класса ячейки попробуйте позвонить:

- (void)prepareForReuse {
    [super prepareForReuse];
    [self setHighlighted:NO];
    ... Any other custom stuff that should be cleaned up ...
}

Проблема заключается в том, что вы, вероятно, делаете фоновое окрашивание по-разному, тогда ячейка обычно делает это самостоятельно, когда подсвечивается. Обычно суперкласс класса отменяет эти изменения в prepareForReuse, но он не знает о ваших изменениях.

Ответ 2

В качестве обходного пути я использовал следующее:

// Both highlightedData and lastHighlightedData are only needed if you want to prevent user from selecting a cell which data changed during the reload. If not needed, a boolean may be used instead
@property (nonatomic) id highlightedData;
@property (nonatomic) id lastHighlightedData;
@property (nonatomic) BOOL pendingCollectionViewReload;

// Wrap the reloadData call. Enqueue it if there a highlighted cell:
- (void)reloadCollectionView
{
    if (self.highlightedData) {
        self.pendingCollectionViewReload = YES;
        return;
    }

    [self.collectionView reloadData];
    self.pendingCollectionViewReload = NO;
}

// When a cell is highlighted, save its index, or better the related data:
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    // Save data at indexPath to self.highlightedData
}    

// Then reload the data when the cell is unhighlighted:
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    self.lastHighlightedData = self.highlightedData;
    self.highlightedData = nil;

    if (self.pendingCollectionViewReload) {
        [self reloadCollectionView];
    }
}

// The following can be used from shouldPerformSegueWithIdentifier or didSelectItemAtIndexPath to prevent actions if the data associated with the indexPath changed:
- (BOOL)selectedDataEquals:(id)data
{
    // I used lastHighlightedData in addition to highlightedData because this function may be used after the didUnhighlightItemAtIndexPath was called:
    return (self.highlightedData && self.highlightedData == data) || (!self.highlightedData && self.lastHighlightedData == data);
}

Ответ 3

Я столкнулся с той же проблемой в представлении коллекции, который не нуждался в подсветке, и я заметил, что методы didHighlight/didUnhighlight ведут себя правильно, поэтому я закончил блокировку перезагрузок во время касания, используя что-то вроде этого:

BOOL blockColviewUpdate,colviewUpdateQueued;

а затем

-(void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    blockColviewUpdate=YES;
}

-(void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    blockColviewUpdate=NO;
    if(colviewUpdateQueued==YES) [self CollectionViewRefresh];
}

при использовании собственной функции вместо прямого вызова reloadData:

-(void)CollectionViewRefresh
{
    if(blockColviewUpdate==YES) colviewUpdateQueued=YES;
    else
    {
        colviewUpdateQueued=NO;
        [self.colview reloadData];
    }
}

Это помогло в моем случае, и никакие перезагрузки не были потеряны.

Ответ 4

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

    - (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:    (NSIndexPath *)indexPath
{
    return YES;
}

- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath;
{
    return YES;
}

В подклассе collectionviewcell

@interface SalesLegendCell: UICollectionViewCell

ниже приведен код

    - (id)initWithFrame:(CGRect)frame {    
    self = [super initWithFrame:frame];    
    if (self) {
        // Initialization code
        NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"SalesLegendCell" owner:self options:nil];

        if ([arrayOfViews count] < 1) {
            return nil;
        }

        if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[SalesLegendCell class]]) {
            return nil;
        }

        self = [arrayOfViews objectAtIndex:0];

        UIView* backgroundView = [[UIView alloc] initWithFrame:self.bounds];
        backgroundView.backgroundColor = [UIColor colorWithWhite:0.85 alpha:1];

        UIView* selectedBGView = [[UIView alloc] initWithFrame:self.bounds];
        selectedBGView.backgroundColor = [UIColor colorWithWhite:1.0 alpha:1];

        self.selectedBackgroundView = backgroundView;
        self.backgroundView = selectedBGView;        
    }
    return self;
}