Citrrus / MBContactPicker

iOS7 Styled Contact Picker Library that uses a UICollectionView
MIT License
501 stars 60 forks source link

UICollectionView crash during dealloc after rotation from landscape to portrait #66

Closed lttldrgn closed 10 years ago

lttldrgn commented 10 years ago

I experienced a strange crash when the contact picker is deallocated when the parent view controller is destroyed, but only after rotating from landscape to portrait. I can reproduce the issue with the project example storyboard by creating a new initial view that pushes to the example VC. Rotate the device to landscape and back to portrait, pop the view and you get the following:

2014-03-13 22:20:57.143 MBContactPicker[14727:60b] *\ Assertion failure in -[MBContactCollectionView dealloc], /SourceCache/UIKit_Sim/UIKit-2935.137/UICollectionView.m:654

Enabling zombie objects gives you a bit more information. 2014-03-13 22:23:28.671 MBContactPicker[14765:60b] *\ -[MBContactCollectionViewFlowLayout respondsToSelector:]: message sent to deallocated instance 0x10925db80

Attempting to hold onto the layout object in a member variable results in the following giving a bit more information: 2014-03-13 22:27:25.632 MBContactPicker[14840:60b] *\ Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView (<MBContactCollectionView: 0x109857600; baseClass = UICollectionView; frame = (0 0; 320 31); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x109277bc0>; layer = <CALayer: 0x109273950>; contentOffset: {0, 0}> collection view layout: <MBContactCollectionViewFlowLayout: 0x109281390>) was deallocated while an update was in flight'

It appears some update to the layout is queued up after the dealloc is slated to run. A change that seemed to fix the problem and retain functionality is modifying the MBContactCollectionView forceRelayout function from:

[self performBatchUpdates:nil completion:nil];

to

MBContactCollectionViewFlowLayout *layout = MBContactCollectionViewFlowLayout*)self.collectionViewLayout;
[layout finalizeCollectionViewUpdates];
mhupman commented 10 years ago

Whew! This was quite the bug, thanks for the detailed investigation. The problem seemed to occur when multiple calls to performBatchUpdates:completion: were made immediately in quick succession, which only seemed to happen (at least in the sample app) when rotating from landscape back to portrait. I played around with combinations of serial performBatchUpdates:completion:, invalidateLayout, and finalizeCollectionViewUpdates. I think I have a working fix in #71.