2

I have a UICollectionView, and I use reloadItemsAtIndexPaths:@[path] to update it. However, sometimes, not quite often, I got a crash from reloadItemsAtIndexPaths:@[path]. I have been thinking about the reason, but cannot figure out one.

Could some one share some ideas about this? e.g. how to narrow down the bug, add what log messages, etc. and possible reason for it?

The trace shows:

Crashed: com.apple.main-thread
EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x0000000000000010 
Thread : Crashed: com.apple.main-thread
0  libobjc.A.dylib                0x0000000192a63bd0 objc_msgSend + 16
1  UIKit                          0x000000018714e88c -[UICollectionViewFlowLayout _updateDelegateFlags] + 88
2  UIKit                          0x000000018714f83c -[UICollectionViewFlowLayout _fetchItemsInfoForRect:] + 304
3  UIKit                          0x0000000186c2877c -[UICollectionViewFlowLayout prepareLayout] + 184
4  UIKit                          0x0000000186b1296c -[UICollectionViewData _prepareToLoadData] + 76
5  UIKit                          0x0000000186c8b17c -[UICollectionView _endItemAnimations] + 7780
6  MCompass                       0x0000000100052270 reloadItemsAtIndexPaths:
Wingzero
  • 9,644
  • 10
  • 39
  • 80
  • EXC_BAD_ACCESS usually means that a call was made to something that isn't an object (i.e. something that was dealloced). Enabling NSZombies helps with that (see http://stackoverflow.com/questions/5386160/how-to-enable-nszombie-in-xcode) – Juan Feb 25 '15 at 04:31
  • 1
    it is not easy to reproduce with Xcode. I got this crash in field, so I am hard to tell which object is deallocated. – Wingzero Feb 25 '15 at 05:08
  • 1
    According to https://beyondrainbowsandunicorns.wordpress.com/2014/02/13/objc_msgsend-goes-boom/ a crash in that method means your delegate/datasource got dealloced – Juan Feb 25 '15 at 17:05
  • Yes I found out that too. Thanks! – Wingzero Feb 26 '15 at 01:10

2 Answers2

1

It seems that you need to add this:

- (void)dealloc
{
   collectionView.delegate = nil;
   collectionView.dataSource = nil;
}
ChikabuZ
  • 10,031
  • 5
  • 63
  • 86
0

Besides setting your delegate and datasource to nil,make sure to capture weak references in closures. Here's an example:

        __weak __typeof__(collectionView) weakView = _collectionView;

        [[Communicator sharedInstance] fetchImageData:imageURL completion:^(NSData * _Nullable imageData) {
            __strong  __typeof__(weakView) strongView = weakView;
            // ...
            [strongView reloadItemsAtIndexPaths:@[indexPath]];
        }];

This was solved with capture lists in Swift. See https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID56

Karoly Nyisztor
  • 3,505
  • 1
  • 26
  • 21