上的访问错误
我在我的UICollectionView中遇到了一个奇怪的崩溃。 崩溃的UICollectionViewembedded在另一个UICollectionView的UICollectionView单元格中。
我不能重现这个问题,它似乎有时如果内部UICollectionView得到新的初始化,因为外面的CollectionView正在重新加载它的单元格。
com.apple.main-thread崩溃 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第52行 - [BSCTopnewsCollectionView setupBSCTopnewsCollectionView] 7 MyApp BSCTopnewsCollectionView.m第27行 - [BSCTopnewsCollectionView setWeakDelegatePointer:] 8 Myapp BSCFrontPageViewController.m 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 QuartzCore CA :: Context :: commit_transaction(CA :: Transaction *)+ 238 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 UIKit UIApplicationMain + 1120 26 MyApp main.m行16主要 例外types: EXC_BAD_ACCESS 码: KERN_INVALID_ADDRESS在0x158848
我在setupBSCTopnewsCollectionView的第52行做的是
BSCInfiniteLayout * infiniteLayout = [[BSCInfiniteLayout alloc] init]; (第52行)self.collectionView.collectionViewLayout = infiniteLayout;
编辑: – [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]; }
编辑3 :崩溃似乎只发生在特殊场合。 如果应用程序在后台,但仍然在内存中,用户再次打开它。 然后检查我们的API是否有新的数据,如果发现有东西会加载它们并重新加载整个外部 collectionView。 那就是当发生崩溃的时候。
如果CollectionView在应用程序运行时重新加载而不在开始的背景中,则一切正常。
为了使设置更清晰一点。
首先,将UICollectionView拖放到XIB中的ViewController中,将Delegate,datasource连接到ViewController(这只是主ViewController)
不要为1个CollectionView使用2个不同的笔尖单元,因为您只能注册1个笔尖。 更好地使用DecorationView作为HeaderView。 创build新的类HeaderView:UICollectionReusableView。 这个UICollectionReusableView是UIView的子类,可以和UICollectionViewCell一起在UICollectionView里面重用。 现在你可以注册这两种types:
[self.collectionView registerNib:[UINib nibWithNibName:@"MyCell" bundle:nil] forCellWithReuseIdentifier:@"CELL"]; [self.collectionView registerNib:[UINib nibWithNibName:@"HeaderView" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderCell"];
接下来,将另一个UICollectionView拖到这个HeaderView中,与HeaderView.h中的IBOutlet连接起来。 在这里,最好将Delegate,DataSource设置为这个类来进行控制。 还要注册这个CollectionView将使用的Nib Cell。 在awakeFromNib中执行,因为你之前注册了Nib
- (void)awakeFromNib{ [self.topCollectionView registerNib:[UINib nibWithNibName:@"TopCell" bundle:nil] forCellWithReuseIdentifier:@"TopCell"]; [self.topCollectionView setDataSource:self]; [self.topCollectionView setDelegate:self]; }
如果将数据源存储在外部,只需创build另一个属性并将其分配给数据源,然后在此处使用数据源返回即可。
如果你想知道什么时候点击了headerView中的Cell,使用customDelegate协议在单击HeaderCell时将委托发送到ViewController。
这是我的代码,希望你明白,并可以在这里应用你的数据:
https://github.com/lequysang/gitfiles02/blob/master/CollectionViewWithDecorationView.zip
看起来像你的委托或内部集合视图已经死了(什么setWeakDelegatePointer:做?)。 尝试在模拟器上的僵尸仪器,它应该标志如果僵尸的情况下。 还为xCode中的所有exception设置“Exceptions breakpoint”(将帮助您在从xCode运行应用程序时debugging而不是仪器)。 同时检查你的-[BSCFrontPageViewController collectionView:cellForItemAtIndexPath:]
实现,它可能会释放内部收集视图的重用。
编辑:为什么不只是添加标题单元格作为标题,而不是单元格0( 这里集合视图中的标题的例子)? 另外检查(只是为了确保它不是一个崩溃的原因)你的重用标识符,当你创buildg外部收集视图的正常单元格。 在模拟器上进行debugging时,也会定期发送mem警告。
另外,为什么使用另一个集合视图的标题? 你可以使用类似于iCarousel的东西来做这样的布局。
你可以尝试下面的方式,滚动主要uicollectionview所以标题不显示…(进一步更好)然后在模拟器上尝试执行内存警告…使用硬件 – >模拟内存警告…
这应该可能会创build一个单元格回收和删除(uicollectionview应该摧毁任何不重要的东西现在…如果发生这种情况,头将被解除分配,你仍然有一个薄弱的参考…所以你做的任何事情将会发生,因为访问不良…也是由于缺乏内存警告(只有你以明确的方式创build的)在模拟器上重现的“不可能的”..
视图看起来很重,所以你可以尝试这样做,并发布结果?
从评论中拉出我们的“答案”。
可悲的是没有任何答案帮助。 我最终重构了整个事情,然后问题消失了。 我甚至与一位苹果DTS工程师进行了非常详细的交谈,他也不知道该怎么做。 所以我们只是重构。 对不起:/