3

短的問題:如何UICollectionView補充意見被正確插入或刪除

有沒有辦法在類似insertItemsAtIndexPaths:deleteItemsAtIndexPaths:甚至reloadItemsAtIndexPaths:方法performBatchUpdates:塊添加和刪除樣細胞和部分補充意見?

龍解釋:

我使用UICollectionView與部分。單元佈局如同一個網格,每條線最多可以有6個單元。如果單元格的總數不填滿某個部分的所有行,我會添加其他補充視圖。額外的補充意見只是填補了空白空間。所以結果應該是每個部分完全充滿所有可用的單元格,並且(可能的)剩餘的空白點充滿補充視圖。所以每條線都有6個可視元素,可以查看單元格或補充視圖。

爲了實現這個目標,我實現一個自定義的UICollectionViewFlowLayout基於佈局具有以下prepareLayout:實現:

- (void)prepareLayout { 
    [super prepareLayout]; 

    self.supplementaryViewAttributeList = [NSMutableArray array]; 
    if(self.collectionView != nil) { 
     // calculate layout values 
     CGFloat contentWidth = self.collectionViewContentSize.width - self.sectionInset.left - self.sectionInset.right; 
     CGFloat cellSizeWithSpacing = self.itemSize.width + self.minimumInteritemSpacing; 
     NSInteger numberOfItemsPerLine = floor(contentWidth/cellSizeWithSpacing); 
     CGFloat realInterItemSpacing = (contentWidth - (numberOfItemsPerLine * self.itemSize.width))/(numberOfItemsPerLine - 1); 

     // add supplementary attributes 
     for (NSInteger numberOfSection = 0; numberOfSection < self.collectionView.numberOfSections; numberOfSection++) { 
      NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:numberOfSection]; 
      NSInteger numberOfSupplementaryViews = numberOfItemsPerLine - (numberOfItems % numberOfItemsPerLine); 

      if (numberOfSupplementaryViews > 0 && numberOfSupplementaryViews < 6) { 
       NSIndexPath *indexPathOfLastCellOfSection = [NSIndexPath indexPathForItem:(numberOfItems - 1) inSection:numberOfSection]; 
       UICollectionViewLayoutAttributes *layoutAttributesOfLastCellOfSection = [self layoutAttributesForItemAtIndexPath:indexPathOfLastCellOfSection]; 

       for (NSInteger numberOfSupplementor = 0; numberOfSupplementor < numberOfSupplementaryViews; numberOfSupplementor++) { 
        NSIndexPath *indexPathOfSupplementor = [NSIndexPath indexPathForItem:(numberOfItems + numberOfSupplementor) inSection:numberOfSection]; 
        UICollectionViewLayoutAttributes *supplementaryLayoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:ARNCollectionElementKindFocusGuide withIndexPath:indexPathOfSupplementor]; 
        supplementaryLayoutAttributes.frame = CGRectMake(layoutAttributesOfLastCellOfSection.frame.origin.x + ((numberOfSupplementor + 1) * (self.itemSize.width + realInterItemSpacing)), layoutAttributesOfLastCellOfSection.frame.origin.y, self.itemSize.width, self.itemSize.height); 
        supplementaryLayoutAttributes.zIndex = -1; 

        [self.supplementaryViewAttributeList addObject:supplementaryLayoutAttributes]; 
       } 
      } 
     } 
    } 
} 

這個偉大的工程,如果所有數據都可用從一開始就,如果沒有對數據沒有變化。但是,如果數據在生命週期中被添加和刪除,它會失敗。插入和刪除performBatchUpdates:中的單元格會混淆補充視圖。

應該發生什麼:

對於每一個被插入insertItemsAtIndexPaths:的補充視圖在同一indexPath應去除細胞。此外,對於使用deleteItemsAtIndexPaths:刪除的每個單元格,都應在相同的indexPath處添加新的補充視圖。

問題:

我佈局的prepareLayout:被調用,計算正確layoutAttributes。但layoutAttributesForSupplementaryViewOfKind:atIndexPath:被稱爲奇怪indexPaths。具體而言,layoutAttributesForSupplementaryViewOfKind:atIndexPath:被稱爲舊的indexPaths,它已從supplementaryViewAttributeList陣列中刪除!

例子:

在新小區被插入的情況下,prepareLayout:正確刪除layoutAttributes,但layoutAttributesForSupplementaryViewOfKind:atIndexPath:仍然得到所要求的不再可用,並刪除indexPath!僅此而已。對於所有其他補充視圖,沒有任何其他indexPath的額外呼叫。

爲什麼layoutAttributesForSupplementaryViewOfKind:atIndexPath:要求indexPaths不再可用?我將如何正確刪除,插入或重新加載補充視圖?我錯過了什麼?

來源:

完整的源可以在這裏找到:

自定義佈局:https://github.com/sarn/ARNClassicFilms/blob/master/classicFilms/classicFilms/layout/ARNCollectionViewFocusGuideFlowLayout.m

的CollectionView控制器: https://github.com/sarn/ARNClassicFilms/blob/master/classicFilms/classicFilms/view-controllers/ARNMovieOverviewController.mperformBatchUpdates:是在類的最後方法)

+0

嘿,我剛剛發生了你的帖子,並想知道你是否發現了什麼?我遇到[非常類似的問題](http://stackoverflow.com/questions/38005641/no-uicollectionviewlayoutattributes-instance-for-layoutattributesforsupplementa/38005845#38005845) – Genhain

+1

我上週實際上在WWDC上詢問了一位Apple工程師。他提供的解決方案是向'performBatchUpdates:'塊添加一個'[[collectionView collectionViewLayout] invalidateLayout];'。這實際上適用於我的情況。也許這可以幫助你的情況,以及 –

+0

意思是我很接近,我在塊前添加它,將嘗試並更新我的問題,如果它是富有成果的。 – Genhain

回答

1

一個解決方案是將第[[collectionView collectionViewLayout] invalidateLayout]添加到第e performBatchUpdates:區塊。這會強制佈局重新計算並刪除無效的索引路徑。

2

您的評論並不是我爲什麼做的,我發現了另一個代碼並添加了它,它的工作,甚至刪除了上述建議,它仍然工作。收集意見肯定是強大的,但忘了一個功能,如這一個...

- (NSArray<NSIndexPath *> *)indexPathsToDeleteForSupplementaryViewOfKind:(NSString *)elementKind 
{ 
    return self.removedIndexPaths; 
} 

和事情可以相當錯誤。