Почему pop to root не работает в этом примере кода SwiftUI?

#swiftui

#swiftui

Вопрос:

Для целей этого вопроса я предоставил минимальный пример кода для повторного создания ошибки. Просто скопируйте / вставьте его для запуска.

 import SwiftUI

final class Popper: ObservableObject {
    @Published var shouldProceed: String? = nil
    var id: String
    init(id: String) { self.id = id }
}

struct ContentView: View {
    @StateObject var popper = Popper(id: "ROOT")
    
    var body: some View {
        NavigationView {
            VStack(spacing: 40) {
                Text("You are now in ROOT").font(.largeTitle)
                Text("Tap Here to goto V1").onTapGesture {
                    popper.shouldProceed = "y"
                }.foregroundColor(.blue)
                NavigationLink(destination: V1().environmentObject(popper),
                               tag: "y",
                               selection: $popper.shouldProceed) {
                    EmptyView()
                }
            }
        }
    }
}

struct V1: View {
    @EnvironmentObject var rootPopper: Popper
    @StateObject var v1Popper = Popper(id: "V1")
    var body: some View {
        VStack(spacing: 40) {
            Text("You are now in V1").font(.largeTitle)
            Text("Tap Here to pop to root").onTapGesture {
                print("popping to: (rootPopper.id)")
                rootPopper.shouldProceed = nil
            }.foregroundColor(.red)
            
            Text("Or tap here to go to V2").onTapGesture {
                v1Popper.shouldProceed = "y"
            }.foregroundColor(.blue)
            NavigationLink(destination: V2().environmentObject(v1Popper),
                           tag: "y",
                           selection: $v1Popper.shouldProceed) {
                EmptyView()
            }
            
        }
    }
}

struct V2: View {
    @EnvironmentObject var v1Popper: Popper
    @State var shouldProceed: String? = nil
    var body: some View {
        VStack(spacing: 40) {
            Text("You are now in V2").font(.largeTitle)
            Text("Tap Here to pop to V1").onTapGesture {
                print("popping to: (v1Popper.id)")
                v1Popper.shouldProceed = nil
            }.foregroundColor(.red)
            
            Text("Or Tap here to gotoV3").onTapGesture {
                shouldProceed = "y"
            }.foregroundColor(.blue)
            NavigationLink(destination: V3().environmentObject(v1Popper),
                           tag: "y", selection: $shouldProceed) {
                EmptyView()
            }
            
        }
    }
}

struct V3: View {
    @EnvironmentObject var v1Popper: Popper
    var body: some View {
        VStack(spacing: 40) {
            Text("You are now in V3").font(.largeTitle)
            
            Text("Tap Here to pop to V1").onTapGesture {
                print("popping to: (v1Popper.id)")
                v1Popper.shouldProceed = nil
            }.foregroundColor(.red)
        }
    }
}
  

Вопрос: Когда вы переходите к экрану V3, почему он не появляется на экране V1? Все остальные функции pop работают. По какой-то причине он просто терпит неудачу, когда доходит до screen V3.
Пожалуйста, помогите.

Ответ №1:

Попробуйте использовать .isDetailLink(false) для ваших ссылок, например

 NavigationLink(destination: V1().environmentObject(popper),
               tag: "y",
               selection: $popper.shouldProceed) {
    EmptyView()
}.isDetailLink(false)     // << here !!
  

Комментарии:

1. Я не вижу документации о том, почему это работает. У вас есть объяснение?

2. неужели этому никто не объясняет?

3. @FlowUI.SimpleUITesting.com , если вы ищете официальный ответ на вопрос, почему , то его нет. Эмпирически этот флаг влияет на то, как строится стек внутренних ссылок — он либо плоский ( isDetailLink ==false ), и тогда все теги расположены в одном пространстве — так что решение работает, либо не плоский, и тогда каждая показанная ссылка вводит новое пространство тегов, и мы наблюдаем поведение, как в исходном вопросе.