频繁重新加载 collectionView 时崩溃 [英] Crash when reloading collectionView frequently

查看:47
本文介绍了频繁重新加载 collectionView 时崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In an iOs app I am using a collection view that will frequently be update when the user taps on a cell in a different collectionView that is onscreen. The collection view receives data one row at a time and reloads the 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
}

如您所见,数据字典已重置.

As you can see the data dictionarys are reset.

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

这里接收到1行数据,添加到相关词典中使用.这是布局代码:

Here 1 row of data is received and added to the relevant dictionaries for use. This is the layout code:

@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 次),应用会崩溃:

The problem is that sometimes if you switch the data (taps on the collection view code shown in 1st code snippet) very frequently (like 2 taps a second) the app crashes:

*** 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 中的重新加载和 did 接收数据中的重新加载之间的某种干扰.切换时我确实取消了所有数据请求,但不知何故过了一会儿,集合视图似乎进入了这种混乱状态并崩溃了.

I believe this is some sort of interference between the reloads in the didSelectCell and the reload in the did receive data. I do cancel all data requests when switching but somehow after a while it seems the collection view enters this confused state and crashes.

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

How can I prevent this crash?

推荐答案

我想我明白了.问题出在 numberOfCellsInSection 中.如果没有数据可用,我将返回 0,但显然该方法的调用频率不够高,因此当数据可用时,它仍然期待 0.将其更改为返回 100,并且不再出现崩溃.

I think I figured it out. The problem was in numberOfCellsInSection. There I was returning 0 if no data was available, but apparently that method isn't called often enough so when data was available it was still expecting 0. Changed that to return 100 and haven't seen the crash anymore.

这篇关于频繁重新加载 collectionView 时崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆