簡體   English   中英

UICollectionView不重用單元格

[英]UICollectionView doesn't reuse cell

我正在嘗試使用UICollectionView模仿UITableView布局。

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

我注冊了可重用的單元格類。

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

注意: SampleClass只是UICollectionViewCell的子類, 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記錄子視圖的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次。

我確實在工作,由於更積極的緩存,它只是保留了更多的內存。 如果嘗試將項目數從28更改為100,則滾動時會看到它停留在33個子視圖中。

嘗試將以下代碼添加到您的SampleCell類中,您將看到它被調用,但是可能與您期望的不太一樣。

- (void)prepareForReuse {
    [super prepareForReuse];

    NSLog(@"prepareForReuse called");
}

UICollectionView具有比UITableView更高級的緩存方案(或至少與以前一樣),這就是您看到自己要做什么的原因。 根據文檔,它說默認情況下啟用單元預取

UICollectionView提供了兩種預取技術,可用於提高響應速度:

  • 單元格預取會在所需時間之前准備單元格。 當集合視圖同時需要大量單元格(例如,網格布局中有新的單元格行)時,將比顯示所需的時間更早地請求這些單元格。 因此,單元格渲染分布在多個布局通道中,從而帶來更流暢的滾動體驗。 默認情況下啟用單元預取。

  • 數據預取提供了一種機制,通過該機制可以在對單元的請求之前將收集視圖的數據需求通知給您。 如果單元格的內容依賴於昂貴的數據加載過程(例如網絡請求),這將很有用。 將符合UICollectionViewDataSourcePrefetching協議的對象分配給prefetchDataSource屬性,以接收有關何時為單元格預取數據的通知。

  • 您可以通過setupCollectionView添加到示例中的setupCollectionView函數來關閉單元格預取:

    self.collectionView.prefetchingEnabled = NO;
    

    這樣做將使您的示例按預期工作。 在我的情況下,子視圖數將降至18。

    我懷疑對子視圖進行計數不能反映單元格的重用。 子視圖可能包含多個對同一單元的引用。 要計算使用的單元格數量,您可以記錄UICollectionViewCell子類初始化的次數。 只需重寫它的init方法,然后在其中放置一條打印語句即可。

    要注意的另一件事(對不起,如果很明顯的話),如果所有單元格都在屏幕上可見,則不會發生重用。 當單元在滾動過程中離開屏幕時,就會發生單元重用。

    暫無
    暫無

    聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

     
    粵ICP備18138465號  © 2020-2024 STACKOOM.COM