1

I have a project with 4 main views. Here is the body of the ContentView containing the NavigationView. I added the modifier .navigationViewStyle(StackNavigationViewStyle()) so I don't get the split view navigation in landscape mode.

ContentView.swift:

var body: some View {
        NavigationView {
            VStack(alignment: .center, spacing: 10) {
                Text("Scoreboard")
                .font(.custom("Chalkduster", size: 50))
                
                Button(action: {
                    self.new_game = true
                }) {
                    Text("New Game")
                    .font(.custom("Chalkduster", size: 20))
                    .foregroundColor(.black)
                }
                
                NavigationLink(destination: CreateGameView(TEST_NAV: self.$new_game), isActive: $new_game) {
                    EmptyView()
                }
                //.isDetailLink(false)
            }
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }

This is causing my app to crash under certain circumstances and I'm not sure why. It is also caused if I remove this line but add the .isDetailLink(false) to every NavigationLink (I have one on ContentView.swift, CreateGameView.swift, and GameView.swift). I am not sure how to show the issue succinctly with a few code snippets so I think the best way is to provide the entire project with the steps to recreate the crash. Here is the github for the project: https://github.com/steve3424/scoreboard_project

To recreate crash:

  1. Start the simulator.
  2. Click "New Game".
  3. Add any title and at least one player.
  4. Start game.
  5. Do 1 of 2 things:
    • Long tap the "Round 1" label to bring up context menu (This will cause what I think is a warning "unable to simultaneously satisfy constraints". I don't think this is a problem though)
    • Click and drag the "Round 1" label to up or down
  6. Navigate back and the app will crash with "precondition failure: invalid index 2". A SIGABRT happens on line 65 of GameView.swift.

From what I have read:

precondition failure: invalid input index when using GeometryReader in SwiftUI starting with iOS 13.4

How to debug "precondition failure" in Xcode?

https://www.reddit.com/r/iOSProgramming/comments/eis04m/precondition_failure_invalid_input_index/

I think it has something to do with the GeometryReader. The only place I use GeometryReader is here:

GameView.swift line 29:

struct TrackableScrollView<Content>: View where Content: View {
    let axes: Axis.Set
    let showIndicators: Bool
    @Binding var contentOffset: CGFloat
    let content: Content
    
    init(_ axes: Axis.Set = .vertical, showIndicators: Bool = true, contentOffset: Binding<CGFloat>, @ViewBuilder content: () -> Content) {
        self.axes = axes
        self.showIndicators = showIndicators
        self._contentOffset = contentOffset
        self.content = content()
    }
    
    var body: some View {
        GeometryReader { outsideProxy in
            ScrollView(self.axes, showsIndicators: self.showIndicators) {
                ZStack(alignment: self.axes == .vertical ? .top : .leading) {
                    GeometryReader { insideProxy in
                        Color.clear
                            .preference(key: ScrollOffsetPreferenceKey.self, value: [self.calculateContentOffset(fromOutsideProxy: outsideProxy, insideProxy: insideProxy)])
                            // Send value to the parent
                    }
                    VStack {
                        self.content
                    }
                }
            }
            .onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
                self.contentOffset = value[0]
            }
            // Get the value then assign to offset binding
        }
    }
    
    private func calculateContentOffset(fromOutsideProxy outsideProxy: GeometryProxy, insideProxy: GeometryProxy) -> CGFloat {
        if axes == .vertical {
            return (insideProxy.frame(in: .global).minY - outsideProxy.frame(in: .global).minY)
        } else {
            return (insideProxy.frame(in: .global).minX - outsideProxy.frame(in: .global).minX)
        }
    }
}

Above is a trackable scrollview created here: https://medium.com/@maxnatchanon/swiftui-how-to-get-content-offset-from-scrollview-5ce1f84603ec

It allows me to get the scroll offset from both the vertical and horizontal scrollviews and match the movement of the main grid.

Now comment out the .navigationViewStyle(StackNavigationViewStyle()) found in the ContentView.swift (shown above). Repeat the steps and the crash should not happen. This is the only thing I have found that fixes the crash.

Does anyone know why this happens? Is there a way to fix this crash without removing .navigationViewStyle(StackNavigationViewStyle())?

Steve Frazee
  • 173
  • 1
  • 7

0 Answers0