My app have been getting crash report for this crash that I can't reproduce yet. I've read several similar problems and they all point out that: You cannot change array while you're enumerating it
Here's the stacktrace:
Collection <NSConcreteHashTable: 0x2833f1fe0> was mutated while being enumerated.
0
CoreFoundation
__exceptionPreprocess
1
libobjc.A.dylib
objc_exception_throw
2
CoreFoundation
-[__NSSingleObjectEnumerator initWithObject:]
arrow_right 3
Foundation
-[NSConcreteHashTable countByEnumeratingWithState:objects:count:]
4
UIKitCore
-[UIPageViewController queuingScrollView:willManuallyScroll:toRevealView:concealView:animated:]
5
UIKitCore
-[_UIQueuingScrollView _notifyDelegateWillManuallyScroll:toRevealView:concealingView:animated:]
6
UIKitCore
__54-[_UIQueuingScrollView _didScrollWithAnimation:force:]_block_invoke
7
UIKitCore
-[_UIQueuingScrollView _didScrollWithAnimation:force:]
8
UIKitCore
-[_UIQueuingScrollView _scrollViewAnimationEnded:finished:]
9
UIKitCore
-[UIAnimator stopAnimation:]
10
UIKitCore
-[UIAnimator _advanceAnimationsOfType:withTimestamp:]
11
QuartzCore
CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long)
12
IOKit
(Missing)
13
CoreFoundation
__CFMachPortPerform
14
CoreFoundation
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
15
CoreFoundation
__CFRunLoopDoSource1
16
CoreFoundation
__CFRunLoopRun
17
CoreFoundation
CFRunLoopRunSpecific
18
GraphicsServices
GSEventRunModal
19
UIKitCore
UIApplicationMain
20
Skywalker
PromoCenterCoordinator.swift - Line 24
main + 24
21
libdyld.dylib
start
What I've tried:
- Looking at the stacktrace, I suspect the problem might be in the class that contains PageViewController, hence I already add @Atomic property wrapper to the only array/collection in that class
Here's the @Atomic property wrapper:
@propertyWrapper
struct Atomic<Value> {
private let lock: NSRecursiveLock
private var value: Value
init(defaultValue: Value) {
self.lock = NSRecursiveLock()
self.value = defaultValue
}
var wrappedValue: Value {
get {
lock.lock()
defer {
lock.unlock()
}
return value
}
set {
lock.lock()
value = newValue
lock.unlock()
}
}
}
- The stacktrace also shows some activity with scrollView, so I also try to make sure that the scrollView is safe from faulty operation
private func configureScrollViewDelegates() {
let subviewCopy: EnumeratedSequence<[UIView]> = view.subviews.enumerated()
for (counter, _) in subviewCopy {
if let scrollSubview = view.subviews[counter] as? UIScrollView {
configureSwipingObserver(scrollView: scrollSubview)
}
}
}
Looking back at the crash, I'm not really sure which part of my code that contains NSConcreteHashTable, any idea/suggestion for me to try? Thank you everyone!