UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Updated: SwiftUI app crashes when going back in a NavigationView

Forums > SwiftUI

UPDATE:

This is even weirder than I thought, it seems to only crash on some devices. See my comment below.

--- Original question ---

I noticed a weird behavior that the app only crashes if I render the NavigationLink destination as a List. Here is code that reproduces the problem:

import SwiftUI

struct TestView: View {
    var crash: Bool
    @State private var isLoading = true
    @State private var result = [String]()

    private func fetch() {
        isLoading = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            self.result = ["a", "b", "c"]
            self.isLoading = false
        }
    }

    var body: some View {
        Group {
            if isLoading {
                Text("loading")
            } else {
                if crash {
                    List {
                        ForEach(0..<result.count, id: \.self) { index in
                            Text(self.result[index])
                        }
                    }
                } else {
                    Text(result.joined(separator: ", "))
                }
            }
        }
        .onAppear(perform: fetch)
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: TestView(crash: true)) {
                    Text("Crashes when going back")
                }
                NavigationLink(destination: TestView(crash: false)) {
                    Text("Does not crash")
                }
            }
        }
    }
}

So if TestView is rendering its content as a Text, it works fine. If it's rendering as a List, the app crashes when hitting the back button in the navigation bar (after letting the loading complete). Am I doing something wrong?

4      

I just ran this on Xcode 11.4 and could not get the app to crash. Hopefully you're seeing the same result.

-Dan

3      

Are you waiting for the loading to complete? It still crashes for me with Xcode 11.4 & iOS 13.4.

3      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

I don't know how to embed video in forums like this so here's a link to a litlte YouTube video of the simulator running your code. I created a new Xcode project just now and copied/pasted your code into it, then ran the app. I wish I could help more other than the "it works on my machine" answer. 😬

https://youtu.be/JdOGhpeg6JU

4      

UPDATED ANSWER

I just updated to 13.4 and put your code back as it was...and it no longer crashes w/ your code. Looks like it may have been a bug that was fixed internally by Apple w/ the latest update.

----- My Original Answer -----

Okay, so I did see the crashing behavior you describe, but not in the simulator. It crasbed when deployed to my physical device runnng iOS 13.31.

In that scenario, I made a change and moved the List so it is the first child of the Group element as below. This is not specifically what you are looking for, this does not crash. It may help you (or Paul?) get closer to what is actually happening.

    var body: some View {
        Group {
            List {
                if isLoading {
                    Text("loading")
                } else {
                    if crash {
                        ForEach(0..<result.count, id: \.self) { index in
                            Text(self.result[index])
                        }
                    } else {
                        Text(result.joined(separator: ", "))
                    }
                }
            }
        }
        .onAppear(perform: fetch)
    }

4      

Thank you for your answers!

OK, so this is getting weirder. It seems that it only crashes on some devices. These are consistent across two different Macs (both running 10.15.4). Simulators with iOS 13.4 if not otherwise specified:

Crashes:

  • iPhone 11 Pro
  • iPhone 8
  • iPhone X (physical device, iOS 13.3.1 & iOS 13.4)
  • iPhone XS (physical device, iOS 13.3.1)

Does not crash:

  • iPhone 11 Pro Max
  • iPhone 11
  • iPhone 8 Plus

3      

Hi

I have the same weird issue on Iphone XS 13.4.1 and Xcode 11.4. Do you why its happening, I try to debug but nothing.

the workaround to put the loding view inside the List its nice and working but its not the Ui / Ux that is hopen.

3      

Hi Ludvig

This seems to be a really interesting topic (based on the view count :-)).

I did have the same problems with your code and I found a solution which works for me (=not crashing): Instead of switching between List and Text while the view is loading, keep the List and overlay it with your "loading screen"

    var body: some View {
        List {
            ForEach(result, id: \.self) { result in
                Text(result)
            }
        }
        .overlay(
            Group {
                if isLoading {
                    Text("loading")
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .background(Color(.systemBackground))
                }
                else {
                    EmptyView()
                }
        })
        .onAppear(perform: fetch)
    }

I hope this works also for you.

Regards Philipp

UPDATED: Sorry, I forgot to revert back the ForEach in my example above... It also works with your ForEach:

            ForEach(0..<result.count, id: \.self) { index in
                Text(self.result[index])
            }

3      

This issue is fully fixed on iOS 14 Beta 3, it no longer crashes nor does it print warnings/error messages on the console. I don't think that there'll be a fix for this in iOS 13, but only time can tell 🤞.

3      

Seems like the culprit is a bug in onAppear. My workaround is using a viewModel and fetch data before showing the view instead.

3      

Im having thesame isuue when i trigger a navigationlink whith a button, sometimes works and sometimes doesnt work, is there any solution ?

3      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.