我的 UICollectionView 发生了奇怪的崩溃。
崩溃的 UICollectionView 嵌入到另一个 UICollectionView 的 UICollectionView 单元格中。
我无法重现这个问题,如果内部 UICollectionView 是新初始化的,有时似乎会发生这种情况,因为外部 CollectionView 正在重新加载它的单元格。
com.apple.main-thread Crashed
0 libobjc.A.dylib objc_msgSend + 9
1 UIKit -[UICollectionViewData _setLayoutAttributes:atGlobalItemIndex:] + 60
2 UIKit __45-[UICollectionViewData validateLayoutInRect:]_block_invoke_0 + 668
3 UIKit -[UICollectionViewData validateLayoutInRect:] + 1408
4 UIKit -[UICollectionViewData layoutAttributesForElementsInRect:] + 82
5 UIKit -[UICollectionView setCollectionViewLayout:animated:] + 1644
6 MyApp BSCTopnewsCollectionView.m line 52 -[BSCTopnewsCollectionView setupBSCTopnewsCollectionView]
7 MyApp BSCTopnewsCollectionView.m line 27 -[BSCTopnewsCollectionView setWeakDelegatePointer:]
8 Myapp BSCFrontPageViewController.m line 550 -[BSCFrontPageViewController collectionView:cellForItemAtIndexPath:]
9 UIKit -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:] + 252
10 UIKit -[UICollectionView _updateVisibleCellsNow:] + 2672
11 UIKit -[UICollectionView layoutSubviews] + 214
12 UIKit -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 258
13 QuartzCore -[CALayer layoutSublayers] + 214
14 QuartzCore CA::Layer::layout_if_needed(CA::Transaction*) + 460
15 QuartzCore CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 16
16 QuartzCore CA::Context::commit_transaction(CA::Transaction*) + 238
17 QuartzCore CA::Transaction::commit() + 316
18 QuartzCore CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 60
19 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 20
25 UIKit UIApplicationMain + 1120
26 MyApp main.m line 16 main
Exception Type:
EXC_BAD_ACCESS
Code:
KERN_INVALID_ADDRESS at 0x158848
我在 setupBSCTopnewsCollectionView 的第 52 行中所做的是
BSCInfiniteLayout *infiniteLayout = [[BSCInfiniteLayout alloc] init];
(line 52) self.collectionView.collectionViewLayout = infiniteLayout;
Edit: -[BSCFrontPageViewController collectionView:cellForItemAtIndexPath:]
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
if([collectionView isEqual:self.collectionView])
{
if(indexPath.row == 0) // Header Cell
{
BSCTopnewsCollectionView *cell = [collectionView dequeueReusableCellWithReuseIdentifier:BSCHeaderReuseIdentifier forIndexPath:indexPath];
cell.dataSource = self;
cell.weakDelegatePointer = self;
self.topNewsCollectionView = cell;
return cell;
}
else
{
//create normal cells
}
}
else if ([collectionView isEqual:self.topNewsCollectionView.collectionView])
{
BSCTopNewsHeaderCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:BSCTopNewsCellReuseIdentifier forIndexPath:indexPath];
BSCNews *topnews = [self.topNews objectAtIndex:indexPath.row];
[cell setEntity:topnews];
return cell;
}
}
对那里的方法调用进行一些说明:
- (void)setWeakDelegatePointer:(BSCFrontPageViewController *)weakDelegatePointer
{
_weakDelegatePointer = weakDelegatePointer;
[self setupBSCTopnewsCollectionView];
[self.collectionView reloadData];
}
- (void)setupBSCTopnewsCollectionView
{
self.collectionView.delegate = self.weakDelegatePointer;
self.collectionView.dataSource = self.weakDelegatePointer;
BSCInfiniteLayout *infiniteLayout = [[BSCInfiniteLayout alloc] init];
infiniteLayout.delegate = self;
// Setup Layout
self.collectionView.collectionViewLayout = infiniteLayout;
self.collectionView.showsHorizontalScrollIndicator = NO;
self.collectionView.pagingEnabled = YES;
// Register Cells
[self.collectionView registerNib:[UINib nibWithNibName:@"BSCTopNewsHeaderCell" bundle:nil] forCellWithReuseIdentifier:BSCTopNewsCellReuseIdentifier];
}
Edit3: The crash only seems to occur in special occasions.
If the app was in the background, but still in memory and the user opens it up again. It then checks our API for new data, and if it found something will load them and reload the whole
outer collectionView. Thats when the crash occurs.
如果在应用程序运行时重新加载 CollectionView 而不是一开始就在后台,一切都很好。
To make the setup a bit more clear.