Investigating strange navigation bug in my iOS app.
I’m using NavigationStack
for push-navigation and a dedicated ObservableObject
Communicator which holds current NavigationStack
‘s path.
What I want to achieve:
Basically, I have a Root top-view and a Child subview. On button’s tap Child view is pushed to the NavigationStack
, and when navigationBar
‘s Back button is pressed, Child view should be popped from stack.
The problem:
When app is running on iOS 16 device, I scroll a Child‘s content and while it is scrolling by inertia I am tapping on Back button, this actions causes a runtime crash(no crashes on iOS 17.3+). Any suggestions or workarounds to solve this issue on iOS 16 would be greatly appreciated!
I managed to extract a minimal reproducing example:
struct RootView: View {
@StateObject var communicator = Communicator()
var body: some View {
NavigationStack(path: $communicator.path) {
VStack {
Button("Go to child") {
communicator.navigate()
}
.buttonStyle(.borderedProminent)
}
.navigationDestination(for: ChildRoute.self) { _ in
// Child view
ScrollView {
LazyVStack {
Color.indigo.frame(height: 400)
Color.red.frame(height: 400)
Color.green.frame(height: 400)
Color.purple.frame(height: 400)
Color.orange.frame(height: 400)
}
}
}
}
}
}
class Communicator: ObservableObject {
@Published var path = NavigationPath()
func navigate() {
DispatchQueue.main.async {
self.path.append(ChildRoute())
}
}
}
struct ChildRoute: Hashable { }
Example’s crash trace:
Simultaneous accesses to 0x283d74f70, but modification requires exclusive access.
Previous access (a modification) started at SwiftUI`<redacted> + 1992 (0x1d5986808).
Current access (a read) started at:
0 libswiftCore.dylib 0x00000001cb55167c <redacted> + 432
1 libswiftCore.dylib 0x00000001cb5518a4 swift_beginAccess + 84
2 SwiftUI 0x00000001d5986040 <redacted> + 944
3 SwiftUI 0x00000001d5af130c <redacted> + 1648
4 SwiftUI 0x00000001d4ff6eec <redacted> + 2422364
5 AttributeGraph 0x00000001f44954ec <redacted> + 520
6 AttributeGraph 0x00000001f4494d9c <redacted> + 424
7 AttributeGraph 0x00000001f44938b4 <redacted> + 844
8 SwiftUI 0x00000001d4d86034 <redacted> + 592
9 SwiftUI 0x00000001d5b7f908 <redacted> + 4112
10 SwiftUI 0x00000001d4db926c <redacted> + 1816
11 SwiftUI 0x00000001d4d8f088 <redacted> + 1256
12 SwiftUI 0x00000001d4ed91d4 <redacted> + 2100
13 SwiftUI 0x00000001d4d8f088 <redacted> + 4956
14 Combine 0x00000001d9bc5d00 <redacted> + 212
15 Combine 0x00000001d9bdd5f8 ObservableObjectPublisher.send() + 596
16 Combine 0x00000001d9bd08bc <redacted> + 140
17 Combine 0x00000001d9c4c3e0 <redacted> + 608
18 Combine 0x00000001d9bbc214 static Published.subscript.setter + 24
19 NavigationOnScrollCrash 0x00000001044ea090 Communicator.path.setter + 220
20 NavigationOnScrollCrash 0x00000001044e879c key path setter for Communicator.path : Communicator + 152
21 libswiftCore.dylib 0x00000001cb2f2274 <redacted> + 324
22 libswiftCore.dylib 0x00000001cb5540fc <redacted> + 56
23 libswiftCore.dylib 0x00000001cb2f43cc swift_setAtReferenceWritableKeyPath + 276
24 SwiftUI 0x00000001d4e68784 <redacted> + 11380
25 SwiftUI 0x00000001d5e022b4 <redacted> + 6980
26 SwiftUI 0x00000001d5ab45e4 <redacted> + 12244
27 SwiftUI 0x00000001d4f8eac4 <redacted> + 7744
28 SwiftUI 0x00000001d4e5520c <redacted> + 20076
29 SwiftUI 0x00000001d4e15394 <redacted> + 1768
30 SwiftUI 0x00000001d4f0bbfc <redacted> + 13212
31 SwiftUI 0x00000001d4e5520c <redacted> + 20076
32 SwiftUI 0x00000001d4dd5698 <redacted> + 120
33 SwiftUI 0x00000001d4e5520c <redacted> + 20076
34 SwiftUI 0x00000001d591c6c8 <redacted> + 16172
35 SwiftUI 0x00000001d591c6c8 <redacted> + 4952
36 SwiftUI 0x00000001d5e040a8 <redacted> + 7924
37 SwiftUI 0x00000001d5986040 <redacted> + 2044
38 SwiftUI 0x00000001d5986040 <redacted> + 8044
39 SwiftUI 0x00000001d4e4c768 <redacted> + 6312
40 SwiftUI 0x00000001d573ebac <redacted> + 868
41 SwiftUI 0x00000001d4d819e4 <redacted> + 480
42 SwiftUI 0x00000001d5986040 <redacted> + 1452
43 SwiftUI 0x00000001d5cf4a20 <redacted> + 8448
44 SwiftUI 0x00000001d5cf4a20 <redacted> + 8628
45 UIKitCore 0x00000001d36c3d90 <redacted> + 1564
46 UIKitCore 0x00000001d37760dc <redacted> + 208
47 UIKitCore 0x00000001d382a854 <redacted> + 116
48 UIKitCore 0x00000001d3d7995c <redacted> + 608
49 UIKitCore 0x00000001d45b6768 __UIVIEW_IS_EXECUTING_ANIMATION_COMPLETION_BLOCK__ + 36
50 UIKitCore 0x00000001d3645004 <redacted> + 636
51 UIKitCore 0x00000001d3644028 <redacted> + 436
52 UIKitCore 0x00000001d3643838 <redacted> + 196
53 UIKitCore 0x00000001d3643838 <redacted> + 472
54 QuartzCore 0x00000001d2a54d14 <redacted> + 232
55 libdispatch.dylib 0x0000000104981fdc _dispatch_client_callout + 20
56 libdispatch.dylib 0x0000000104992354 _dispatch_main_queue_drain + 1196
57 libdispatch.dylib 0x0000000104992318 _dispatch_main_queue_callback_4CF + 44
58 CoreFoundation 0x00000001d14396b8 <redacted> + 16
59 CoreFoundation 0x00000001d141a838 <redacted> + 2036
60 CoreFoundation 0x00000001d141fc4c CFRunLoopRunSpecific + 612
61 GraphicsServices 0x000000020b6152c4 GSEventRunModal + 164
62 UIKitCore 0x00000001d39152f0 <redacted> + 888
63 UIKitCore 0x00000001d3915178 UIApplicationMain + 340
64 SwiftUI 0x00000001d4f358cc <redacted> + 2424
65 SwiftUI 0x00000001d4e970f4 <redacted> + 388
66 SwiftUI 0x00000001d4e7fb28 <redacted> + 2820
67 NavigationOnScrollCrash 0x00000001044ec36c static NavigationOnScrollCrashApp.$main() + 40
68 NavigationOnScrollCrash 0x00000001044ec438 main + 12
69 dyld 0x00000001efd17f80 <redacted> + 2528