经常重新加载collectionView时崩溃

时间:2014-08-21 09:18:19

标签: ios objective-c uicollectionview

在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 <noProgs; c++)
        {
            UICollectionViewLayoutAttributes* o = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:c inSection:r]];

            if(o.size.width > 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: <NSIndexPath: 0x18c1be10> {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中的重新加载与确实接收数据中的重新加载之间的某种干扰。我确实在切换时取消了所有数据请求,但不久之后似乎集合视图进入这个混乱状态并崩溃。

如何防止此次崩溃?

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:0)

insertItemsAtIndexPaths:更有效率和高效率,而不是在一次只添加一个视图时重新加载整个视图,也可以防止奇怪的滚动工件。