UICollectionView не использует ячейку повторно - PullRequest
2 голосов
/ 10 июля 2019

Я пытаюсь имитировать макет UITableView с помощью UICollectionView.

layout.itemSize = CGSizeMake(CGRectGetWidth(self.view.bounds), 44.0f);

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

[self.collectionView registerClass:[SampleCell class]
            forCellWithReuseIdentifier:NSStringFromClass([SampleCell class])];

Примечание: SampleClass это просто подкласс UICollectionViewCell, который ничего не содержит.

И соответствует источнику данных:

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 28;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([SampleCell class])
                                                                           forIndexPath:indexPath];

    return cell;
}

Я обнаружил, что SampleCell не используется повторно.Чтобы проверить это, мы можем просто записать количество подпредставлений в UICollectionView.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSLog(@"number of subviews in collection view is: %li", (long)self.collectionView.subviews.count);
}

И после прокрутки я получил этот журнал:

количество подпредставлений в коллекциипредставление: 30

количество подпредставлений в представлении коллекции: 30

количество подпредставлений в представлении коллекции: 30

количество подпредставлений в представлении коллекции: 30

Обратите внимание, что существует 30 подпредставлений (2 из них - индикатор прокрутки).

Это означает, что все 28 элементов отображаются без удаления невидимых ячеек из суперпредставления.Почему это происходит?

Чтобы вам было проще, я сделал пример проекта на Github.https://github.com/edwardanthony/UICollectionViewBug

Обновление:

Я также проверил выделение памяти с помощью отладчика иерархии графиков памяти, и оно выделено 28 раз.

Ответы [ 2 ]

3 голосов
/ 10 июля 2019

Я работаю, он просто сохраняет немного больше памяти из-за более агрессивного кэширования.Если вы попытаетесь изменить количество элементов с 28 до 100, вы увидите, что при прокрутке оно останется равным 33 подпредставлениям.

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

- (void)prepareForReuse {
    [super prepareForReuse];

    NSLog(@"prepareForReuse called");
}

UICollectionView имеет более продвинутую схему кэширования, чем UITableView (или, по крайней мере, как раньше), и именно поэтому вы видите, что делаете,Согласно документам говорится, что Предварительная выборка ячеек включена по умолчанию :

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

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

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

Вы можете отключить предварительную выборку ячеек, добавив эту строку в функцию setupCollectionView в вашемобразец:

self.collectionView.prefetchingEnabled = NO;

Это сделает ваш образец работы, как вы ожидали.Количество подпредставлений уменьшится до 18 в моем случае.

1 голос
/ 10 июля 2019

Я подозреваю, что подсчет подпредставлений не отражает повторное использование ячейки.Возможно, подпредставления содержат более одной ссылки на одну и ту же ячейку.Чтобы подсчитать количество используемых ячеек, вы можете записать, сколько раз инициализируется подкласс UICollectionViewCell.Просто переопределите его метод init и поместите туда оператор print.

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

...