EXC_BAD_ACCESS 关于 [UICollectionView setCollectionViewLayout:]

EXC_BAD_ACCESS on [UICollectionView setCollectionViewLayout:]

我有一个使用自定义 UICollectionViewFlowLayout 的集合视图。此集合视图可以在本地或通过互联网加载图像。如果我在本地加载图像,每个导航都运行良好。但是,如果我通过互联网加载图像,屏幕会在第一次正确加载,但如果您点击图像并转到另一个屏幕,然后从该屏幕返回(它们都在导航控制器中),则有一个'bad access'崩溃。 有谁知道可能是什么原因。

在viewDidLoad中

[self.photosCollectionView registerNib:[UINib nibWithNibName:@"PhotoAlbumPhotosCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:kReuseIdentifierPhotosAlbumPhotosCollectionViewCell];

在视图中会出现

[self fetchImagesFromInternetAsynchronously]; 

self.photosCollectionView.dataSource = self;
self.photosCollectionView.delegate = self;

self.photosCollectionViewFlowLayout = [UICollectionViewFlowLayout new];
self.photosCollectionViewFlowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
self.photosCollectionViewFlowLayout.minimumInteritemSpacing = 2.0f;
self.photosCollectionViewFlowLayout.minimumLineSpacing = 2.0f;

CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
CGFloat cellDimension = (screenWidth - 2*self.photosCollectionViewTrailingSpaceConstraint.constant - 3*self.photosCollectionViewFlowLayout.minimumInteritemSpacing)/4 - 1.0;
CGSize cellSize = CGSizeMake(cellDimension, cellDimension);
[self.photosCollectionViewFlowLayout setItemSize:cellSize];

[self.photosCollectionView setCollectionViewLayout:self.photosCollectionViewFlowLayout];

fetchImagesFromInternetAsynchronously 中,我在获取图像后执行 [self.photosCollectionView reloadData]

这是堆栈跟踪:

stop reason = EXC_BAD_ACCESS (code=1, address=0x8)
frame #0: 0x0000000112da0e09 UIKit`-[UICollectionViewData layoutAttributesForItemAtIndexPath:] + 248
frame #1: 0x0000000112d4f2d3 UIKit`-[UICollectionView _setCollectionViewLayout:animated:isInteractive:completion:] + 1893
frame #2: 0x0000000112d4e86b UIKit`-[UICollectionView setCollectionViewLayout:] + 318
* frame #3: 0x000000010be6b0aa app`-[PhotoAlbumPhotosPickerViewController viewWillAppear:](self=0x00007fd5830d3e00, _cmd="viewWillAppear:", animated=YES) + 1514 at PhotoAlbumPhotosPickerViewController.m:90
frame #4: 0x000000010eec85fd UIKit`-[UIViewController _setViewAppearState:isAnimating:] + 710
frame #5: 0x000000010eec8c98 UIKit`-[UIViewController __viewWillAppear:] + 149
frame #6: 0x000000010eef8a37 UIKit`-[UINavigationController _startCustomTransition:] + 1203
frame #7: 0x000000010ef08cdb UIKit`-[UINavigationController _startDeferredTransitionIfNeeded:] + 712
frame #8: 0x000000010ef09cea UIKit`-[UINavigationController __viewWillLayoutSubviews] + 57
frame #9: 0x000000010f0afc85 UIKit`-[UILayoutContainerView layoutSubviews] + 248
frame #10: 0x000000010ede4e40 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 710

难以置信!

这是最终奏效的方法。如果我在这解决的集合视图中添加页脚视图,甚至会发生类似的崩溃。

替换

self.photosCollectionViewFlowLayout = [UICollectionViewFlowLayout new];

self.photosCollectionViewFlowLayout = (UICollectionViewFlowLayout*)self.photosCollectionView.collectionViewLayout;

或者在 viewWillDisappear 中添加这个(但这并没有消除页脚视图崩溃,所以最好使用第一种方法。

self.photosCollectionView.delegate = nil;
self.photosCollectionView.dataSource = nil;

UIKit 对象不是线程安全的。虽然您没有在您的问题中包含触发此代码的代码,但 fetchImagesFromInternetAsynchronously 可能正在根据方法签名在另一个线程上执行工作。从那个线程 [self.photosCollectionView reloadData] 被调用。集合视图只能从主线程访问:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    [self.photosCollectionView reloadData];
}];