Search code examples
iosswiftuiswiftui-navigationstack

SwiftUI NavigationStack bug - tapping on NavigationLink leads to freeze when destination view contains AppStorage


struct NavStack: View {
    
    @AppStorage("userid") var userid: Int = 0
    
    @State var memes = [MemeModel]()
    @State var path = NavigationPath()
    
    var body: some View {
        NavigationStack(path: $path){
            
            ScrollView(.vertical, showsIndicators: false){
                LazyVStack(spacing: 100){
                    ForEach($memes, id: \.memeid){ meme in
                        MemeView(memes: self.$memes, memeid: meme.memeid)
                    }
                }
            }
            .onAppear{
                memes.append(MemeModel(memeid: 1, title: "meme1", pic: "bla.jpg"))
                memes.append(MemeModel(memeid: 2, title: "meme2", pic: "joo.jpg"))
                memes.append(MemeModel(memeid: 3, title: "meme3", pic: "das.jpg"))
                memes.append(MemeModel(memeid: 4, title: "meme4", pic: "fsf.jpg"))
                memes.append(MemeModel(memeid: 5, title: "meme5", pic: "asd.jpg"))
                memes.append(MemeModel(memeid: 6, title: "meme6", pic: "dfvr.jpg"))
                memes.append(MemeModel(memeid: 7, title: "meme7", pic: "fsfdf.jpg"))
                memes.append(MemeModel(memeid: 8, title: "meme8", pic: "axaxe.jpg"))
            }
        }
    }
}


struct MemeView: View {
    
    @Environment(\.dismiss) var dismiss
    func closeThisView(){

        DispatchQueue.main.async {
            self.dismiss()
        }
    }
    
    @AppStorage("userid") var userid: Int = 0
    
    @Binding var memes: [MemeModel]
    @Binding var memeid: Int
    
    var body: some View {
        
        VStack(spacing: 20){
            Text(String(memeid))

            NavigationLink{
                Comments()
            } label: {
                Text("comments")
            }
        }
    }
}

struct Comments: View {
    
    @AppStorage("userid") var userid: Int = 0
    
    var body: some View {
        VStack{
            Text("comments view")
        }
    }
}

struct MemeModel: Codable {
    var memeid: Int
    var title: String
    var pic: String
}

When I tap on comment then the app freezes. It only happens when the deepest child view (comments) contains AppStorage value and it works when I remove it. When I just use MemeView as NavigationLink (so without having any NavigationLink inside MemeView) then freeze doesn't happen.

How to fix this? Any workaround?

Ofc I've seen the other questions about freezing when using NavigationLink, also outside Stackoverflow, but none of the answers are helping.


Solution

  • Just so everyone knows, I didn't find a solution for that and just stopped using NavigationLink entirely and navigationDestination instead.

    You can still pass all kind of data, like so:

    .navigationDestination(for: DataForComments.self){ selection in
        Comments(path: self.$path,
            memeid: selection.memeid,
            previousMemes: selection.previousMemes)
    }
    

    but if you want to pass bindings from a child view then it doesn't seem to be possible and you have to find workarounds, like using AppStorage and OnChange listener together instead