经常重新加载collectionView时崩溃

在iOs应用程序中,我使用的是一个集合视图,当用户点击屏幕上不同collectionView中的单元格时,该视图会经常更新。 集合视图一次接收一行数据并重新加载collectionView。

以下是选择中的代码:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ if (collectionView == self.datePickerCollectionView) { [[self.PickerCollectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:self.crtDelta inSection:0]] setSelected:NO]; if (self.crtDelta == indexPath.item) { // in case the user taps on the day he allready is on // don't do anything return; } self.crtDelta = indexPath.item; [self.attriburesRectDict removeAllObjects]; [self.CollectionView.collectionViewLayout invalidateLayout]; [self.CollectionView reloadData]; [self.TableView reloadData]; self.DataDict = [NSMutableDictionary new]; } // get data from web manager here } 

如您所见,数据字典被重置。

 - (void)didReceiveDataForSection:(NSInteger)section withDataArray:(NSArray*)data andRectsArray:(NSArray*)rects { self.programsDict[@(index)] = data; self.attriburesRectDict[@(index)] = rects; [self.programsCollectionView reloadData]; } 

这里接收1行数据并将其添加到相关词典中以供使用。 这是布局代码:

 @interface MultipleLineLayout() @property (nonatomic, assign) NSInteger numRows; @end @implementation MultipleLineLayout { CGFloat itemHeight; } -(id)init { if (self = [super init]) { self.scrollDirection = UICollectionViewScrollDirectionHorizontal; itemHeight = 0.0; } return self; } -(CGSize)collectionViewContentSize { NSInteger xSize = self.contentSizeWidth; NSInteger ySize = [self.collectionView numberOfSections] * (itemHeight + PROGRAMS_CELL_SPACING); return CGSizeMake(xSize, ySize); } -(void)prepareLayout { [super prepareLayout]; [self.collectionView setBounces:NO]; if (self.collectionView) { self.numRows = [self.collectionView numberOfSections]; } } - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path { UICollectionViewLayoutAttributes *a = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path]; a.frame = [self.dataSource rectForAttributesForRow:path.row inSection:path.section]; return a; } -(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { NSMutableArray* attributes = [NSMutableArray array]; if (itemHeight == 0.0) { itemHeight = [self.dataSource heightOfProgramCell]; } NSUInteger startRow = floorf(rect.origin.y / itemHeight); NSUInteger endRow = ceilf(CGRectGetMaxY(rect) / (CGFloat)itemHeight); if (endRow >= self.numRows) { endRow = self.numRows ; } for (NSUInteger r = startRow; r < endRow; r++) { NSUInteger noProgs = [self.dataSource numberOfElementsInSection:r]; for (NSUInteger c = 0; c  0) { [attributes addObject:o]; } else { break; } } } return attributes; } - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { return NO; } @end 

问题是,有时如果你经常切换数据(点击第一个代码片段中显示的集合视图代码)(比如每秒2次点击)应用程序崩溃:

 *** Assertion failure in -[UICollectionViewData validateLayoutInRect:], /SourceCache/UIKit/UIKit-2903.23/UICollectionViewData.m:341 2014-08-21 12:14:33.052 du View[365:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView recieved layout attributes for a cell with an index path that does not exist:  {length = 2, path = 0 - 0}' *** First throw call stack: (0x2dd4cf4b 0x385c36af 0x2dd4ce25 0x2e6f4fe3 0x3051c953 0x3051c063 0x3051b8c7 0x304bfda3 0x30146c6b 0x3014247b 0x3014230d 0x30141d1f 0x30141b2f 0x3013b85d 0x2dd181cd 0x2dd15b71 0x2dd15eb3 0x2dc80c27 0x2dc80a0b 0x32981283 0x30524049 0x14c529 0x38acbab7) libc++abi.dylib: terminating with uncaught exception of type NSException 

我相信这是didSelectCell中的重新加载和确实接收数据中的重新加载之间的某种干扰。 我确实在切换时取消了所有数据请求,但不久之后似乎集合视图进入这个混乱状态并崩溃。

我怎样才能防止这次崩溃?

我想我想通了。 问题出在numberOfCellsInSection中。 如果没有数据可用,我返回0,但显然该方法不经常被调用,所以当数据可用时,它仍然期待0.更改为返回100并且还没有看到崩溃。

insertItemsAtIndexPaths:更有效率和更高效insertItemsAtIndexPaths:当一次只添加一个视图时,它不会重新加载整个视图,也会阻止奇怪的滚动工件。