Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash in CollectionViewDiffCalculator #45

Closed
kh0r opened this issue Jan 5, 2017 · 5 comments
Closed

Crash in CollectionViewDiffCalculator #45

kh0r opened this issue Jan 5, 2017 · 5 comments

Comments

@kh0r
Copy link

kh0r commented Jan 5, 2017

Hi,

my app sometimes crashes when updating the CollectionView. Unfortunately I'm not able to reproduce the crashes, but the same code (using the TableViewDiffCalculator) works without problems for my tableviews.

I'm using pagination and want to eliminate possible duplicates - hence the diff function here.

// strongSelf is from a guard clause in the callback
let diff = strongSelf.itemList.diff(newItems)
strongSelf.itemList.append(contentsOf: strongSelf.itemList.apply(diff))

the didset iss correctly triggered with the append

var itemList: Array<Item> = [] {
    didSet {
      self.diffCalculator?.rows = itemList
    }
  }

Relevant crashlog:

#0. Crashed: com.apple.main-thread
0  libsystem_kernel.dylib         0x181562014 __pthread_kill + 8
1  libsystem_pthread.dylib        0x18162a450 pthread_kill + 112
2  libsystem_c.dylib              0x1814d63e0 abort + 140
3  libsystem_malloc.dylib         0x1815a6a38 _nano_vet_and_size_of_live + 330
4  libsystem_malloc.dylib         0x1815a8bf0 _nano_malloc_check_clear + 392
5  libsystem_malloc.dylib         0x1815a7b3c nano_malloc + 44
6  libsystem_malloc.dylib         0x1815962c4 malloc_zone_malloc + 172
7  CoreFoundation                 0x18246615c _CFRuntimeCreateInstance + 312
8  CoreFoundation                 0x182551604 __CFStringCreateImmutableFunnel3 + 2116
9  CoreFoundation                 0x18247034c CFStringCreateCopy + 504
10 CoreFoundation                 0x1825519f0 _CFStringCreateWithFormatAndArgumentsAux2 + 256
11 CoreFoundation                 0x182575b98 _CFLogvEx2Predicate + 156
12 CoreFoundation                 0x182575eec _CFLogvEx3 + 408
13 Foundation                     0x18305c454 _NSLogv + 132
14 Foundation                     0x182f8335c NSLog + 32
15 Foundation                     0x18301f76c -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 64
16 UIKit                          0x188ce90e8 -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:] + 13428
17 UIKit                          0x188cecc34 -[UICollectionView _endUpdatesWithInvalidationContext:tentativelyForReordering:animator:] + 92
18 UIKit                          0x188cecf14 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:] + 384
19 UIKit                          0x188cecd74 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:] + 96
20 UIKit                          0x188ceccf8 -[UICollectionView _performBatchUpdates:completion:invalidationContext:] + 84
21 UIKit                          0x1885c71c0 -[UICollectionView performBatchUpdates:completion:] + 64
22 Dwifft                         0x100f1439c CollectionViewDiffCalculator.rows.setter (Dwifft+UIKit.swift)

Any idea what could be happening here?

@jflinter
Copy link
Owner

jflinter commented Jan 5, 2017 via email

@kh0r
Copy link
Author

kh0r commented Jan 8, 2017

The error message is error for object 0x1703c2df0: Invalid pointer dequeued from free list . There is no exception just a SIGABRT ABORT call.

But, there seem to be two kinds of errors leading to this crash: one with the stacktrace/error above and an NSInternalInconsistencyException:
Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (30) must be equal to the number of items contained in that section before the update (30), plus or minus the number of items inserted or deleted from that section (30 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).:

Stacktrace:

Fatal Exception: NSInternalInconsistencyException
0  CoreFoundation                 0x18f0851b8 __exceptionPreprocess
1  libobjc.A.dylib                0x18dabc55c objc_exception_throw
2  CoreFoundation                 0x18f08508c +[NSException raise:format:]
3  Foundation                     0x18fb3d02c -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]
4  UIKit                          0x19583414c -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:]
5  UIKit                          0x195837c98 -[UICollectionView _endUpdatesWithInvalidationContext:tentativelyForReordering:animator:]
6  UIKit                          0x195837f78 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:]
7  UIKit                          0x195837dd8 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:]
8  UIKit                          0x195837d5c -[UICollectionView _performBatchUpdates:completion:invalidationContext:]
9  UIKit                          0x195114618 -[UICollectionView performBatchUpdates:completion:]
10 Dwifft                         0x100f4c39c CollectionViewDiffCalculator.rows.setter (Dwifft+UIKit.swift)

Thanks for helping, I'm totally clueless here.

@kh0r
Copy link
Author

kh0r commented Jan 18, 2017

Update on my side:

Found this blogpost describing the problem: https://fangpenlin.com/posts/2016/04/29/uicollectionview-invalid-number-of-items-crash-issue/

After changing the way I handle the collection view update it seems to not crash anymore:

var itemList: Array<Item> {
    get {
      if let diffCalculator = self.diffCalculator {
        return diffCalculator.rows
      } else {
        return []
      }
    }
    set {
      self.diffCalculator?.rows = newValue
    }
  }

Which brings me to this question: Is it ok to use the rows of the diffCalculator directly? Or put another way: Is there a reason why you recommend updating the diffcalculator with the didSet observer?

@jflinter
Copy link
Owner

jflinter commented Jan 31, 2017

I think the important thing here is how you implement collectionView:numberOfItemsInSection. You should simply return diffCalculator.rows.count there, as CollectionViewDiffCalculator has an explicit internal workaround for the issue described in that blog post.

@jflinter
Copy link
Owner

(closing as I am fairly certain this is not an internal Dwifft issue.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants