hong's Studio.

UICollectionView的异常记录

字数统计: 677阅读时长: 3 min
2019/10/19 Share

UICollectionView的异常记录

同事在使用UICollectionView时,碰到iOS10的真机上出现crash异常,花了一点时间定位问题后,发现是UICollectionView中的UICollectionViewDelegateFlowLayout回调方法的问题,可能是Apple的bug(iOS12上没有碰到),不过我感觉主要还是控件理解不够透彻的关系,使用不够规范,不然应该可以避开或者绕过。

1
2
3
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath

在上面这个计算cell大小的方法中,调用了[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath]方法。

问题表现

A-在iOS10的真机上出现下面的异常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
reason: '-[NSCFString setSizeHasBeenSet:]: unrecognized selector sent to instance 0x610000076bc0' 
*** First throw call stack:
(
0 CoreFoundation 0x0000000109dd9d4b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x00000001094d921e objc_exception_throw + 48
2 CoreFoundation 0x0000000109e49f04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x0000000109d5f005 ___forwarding_ + 1013
4 CoreFoundation 0x0000000109d5eb88 _CF_forwarding_prep_0 + 120
5 UIKit 0x00000001080d9485 -[UICollectionViewFlowLayout _getSizingInfosWithExistingSizingDictionary:] + 3691
6 UIKit 0x00000001080da97b -[UICollectionViewFlowLayout _fetchItemsInfoForRect:] + 127
7 UIKit 0x00000001080d3504 -[UICollectionViewFlowLayout prepareLayout] + 273
8 UIKit 0x00000001080f3d6c -[UICollectionViewData _prepareToLoadData] + 159
9 UIKit 0x00000001080f4618 -[UICollectionViewData validateLayoutInRect:] + 57
10 UIKit 0x000000010809b6d4 -[UICollectionView layoutSubviews] + 232
11 UIKit 0x0000000107817ab8 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1237
12 QuartzCore 0x0000000106fcdbf8 -[CALayer layoutSublayers] + 146
13 QuartzCore 0x0000000106fc1440 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
14 QuartzCore 0x0000000106fc12be _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
15 QuartzCore 0x0000000106f4f318 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 280
16 QuartzCore 0x0000000106f7c3ff _ZN2CA11Transaction6commitEv + 475
17 QuartzCore 0x0000000106f7cd6f _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 113
18 CoreFoundation 0x0000000109d7e267 CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION + 23
19 CoreFoundation 0x0000000109d7e1d7 __CFRunLoopDoObservers + 391
20 CoreFoundation 0x0000000109d628a6 CFRunLoopRunSpecific + 454
21 UIKit 0x000000010774caea -[UIApplication _run] + 434
22 UIKit 0x0000000107752c68 UIApplicationMain + 159
23 Moden 0x0000000104ab4fbf main + 111
24 libdyld.dylib 0x000000010ad4e68d start + 1
) libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

B-在iOS9、iOS10的模拟器上出现下面的异常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2019-10-19 23:02:29.148 UICollectionViewDemo[20163:418963] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(
0 CoreFoundation 0x00000001075f534b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010705621e objc_exception_throw + 48
2 CoreFoundation 0x0000000107526f1b -[__NSArrayM objectAtIndex:] + 203
3 UIKit 0x0000000108ab2fcd -[UICollectionViewFlowLayout _getSizingInfosWithExistingSizingDictionary:] + 1623
4 UIKit 0x0000000108ab4cd7 -[UICollectionViewFlowLayout _fetchItemsInfoForRect:] + 127
5 UIKit 0x0000000108aad860 -[UICollectionViewFlowLayout prepareLayout] + 273
6 UIKit 0x0000000108ace0c8 -[UICollectionViewData _prepareToLoadData] + 159
7 UIKit 0x0000000108ad11d5 -[UICollectionViewData layoutAttributesForItemAtIndexPath:] + 39
8 UIKit 0x0000000108a7f1b3 -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:] + 384
9 UIKit 0x0000000108a7fc84 -[UICollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:] + 169
10 UICollectionViewDemo 0x0000000106a7c798 -[ViewController collectionView:cellForItemAtIndexPath:] + 104
11 UICollectionViewDemo 0x0000000106a7c9ff -[ViewController collectionView:layout:sizeForItemAtIndexPath:] + 143
12 UIKit 0x0000000108ab354f -[UICollectionViewFlowLayout _getSizingInfosWithExistingSizingDictionary:] + 3033
13 UIKit 0x0000000108ab4cd7 -[UICollectionViewFlowLayout _fetchItemsInfoForRect:] + 127
14 UIKit 0x0000000108aad860 -[UICollectionViewFlowLayout prepareLayout] + 273
15 UIKit 0x0000000108ace0c8 -[UICollectionViewData _prepareToLoadData] + 159
16 UIKit 0x0000000108ace974 -[UICollectionViewData validateLayoutInRect:] + 57
17 UIKit 0x0000000108a75d12 -[UICollectionView layoutSubviews] + 232
18 UIKit 0x00000001081ed344 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1237
19 QuartzCore 0x000000010d23bcdc -[CALayer layoutSublayers] + 146
20 QuartzCore 0x000000010d22f7a0 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
21 QuartzCore 0x000000010d22f61e _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
22 QuartzCore 0x000000010d1bd62c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 280
23 QuartzCore 0x000000010d1ea713 _ZN2CA11Transaction6commitEv + 475
24 QuartzCore 0x000000010d1eb083 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 113
25 CoreFoundation 0x0000000107599e17 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
26 CoreFoundation 0x0000000107599d87 __CFRunLoopDoObservers + 391
27 CoreFoundation 0x000000010757e4b6 CFRunLoopRunSpecific + 454
28 UIKit 0x0000000108122db6 -[UIApplication _run] + 434
29 UIKit 0x0000000108128f34 UIApplicationMain + 159
30 UICollectionViewDemo 0x0000000106a7cc10 main + 112
31 libdyld.dylib 0x000000010aae068d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

问题处理方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
//测试1
// RHCollectionViewCell *cell = (RHCollectionViewCell *)[self collectionView:collectionView cellForItemAtIndexPath:indexPath];
//测试2
static NSString *identifier = @"CellIdentifier";
RHCollectionViewCell *cell = (RHCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
//测试3
// RHCollectionViewCell *cell = [[RHCollectionViewCell alloc] init];
return [cell sizeOfCell];

// return CGSizeZero;
}

从上面的测试中,1和2在iOS10的模拟器上都出现了上面B中的异常,最后直接通过计算size来解决问题。

问题参考

CATALOG
  1. 1. UICollectionView的异常记录
    1. 1.1. 问题表现
      1. 1.1.1. A-在iOS10的真机上出现下面的异常:
      2. 1.1.2. B-在iOS9、iOS10的模拟器上出现下面的异常:
    2. 1.2. 问题处理方案
    3. 1.3. 问题参考