У меня есть приложение, созданное с помощью NavigationSplitView
, с меню слева и картой справа. Левый вид управляет состоянием карты в зависимости от того, какой вид в данный момент отображается в меню. Раньше я сохранял свою собственную модель состояния маршрутизации для навигации, когда NavigationLinks
активировался с помощью тегов и выбора. Это позволило всегда знать точное состояние маршрутизации приложений. С новым NavigationStack
мы должны использовать NavigationPath
, который нельзя отслеживать, поскольку внутренние значения являются частными.
Другой вариант, который у нас был ранее, чтобы узнать, когда представление было отклонено, заключался в создании StateObject
для представления при его создании, после чего оно будет освобождено при отклонении представления. Однако это не будет работать в NavigationStack, поскольку новый .navigationDestination
вызывается несколько раз, как и любой тип рендеринга представления, в результате чего StateObject
распределяется и освобождается столько же раз.
И да, я знаю о .onAppear
и .onDisappear
. Однако эти события не имеют значения в этой ситуации, поскольку они могут вызываться несколько раз в течение жизненного цикла представлений, например. когда другой вид представлен поверх текущего вида и т. д.
Можно ли определить, когда представление действительно исчезает (отклоняется) в SwiftUI?
Это не ответ на вопрос, как определить, когда экран исчезает, а скорее решение первой части вашей проблемы.
С NavigationStack
вам не нужно использовать объект NavigationPath
в качестве path
.
Инициализатор:
init(path: Binding<Data>, @ViewBuilder root: () -> Root) where Data : MutableCollection, Data : RandomAccessCollection, Data : RangeReplaceableCollection, Data.Element : Hashable
поэтому path
может быть Binding
любого массива, элементами которого являются Hashable
. например
struct ContentView: View {
enum Routing: Hashable {
case screen1, screen2(String)
}
@State private var path: [Routing] = []
var body: some View {
NavigationStack(path: $path) {
List {
NavigationLink("Show screen 1", value: Routing.screen1)
NavigationLink("Show screen 2", value: Routing.screen2("Fred"))
}
.navigationDestination(for: Routing.self) { screen in
switch screen {
case .screen1:
Text("This is screen 1")
case let .screen2(name):
Text("This is screen 2 - name: \(name)")
}
}
}
.onChange(of: path) { newValue in
path.forEach { screen in
print(screen)
}
}
}
}
Поскольку ваш path
не является непрозрачным объектом, вы можете использовать его для определения текущего состояния вашего приложения.
Возможно, я мог бы изменить дизайн своего приложения, чтобы отображать все представления во всем приложении только из одного .navigationDestination
, но я бы не хотел, если этого можно избежать...
Собственно так я и сделал в итоге. Используя мой собственный массив объектов «Маршрут» и перемещая представление каждого вида в приложении в один .navigationDestination
. Это позволяет мне отслеживать путь и, таким образом, также узнавать, когда представление удаляется из иерархии представлений. Спасибо, что указали мне правильное направление!
Хорошая идея… Я думаю, что хранение всей навигации в одном месте облегчает отслеживание того, что происходит!
Спасибо за ответ! И да, это правда, что вы можете создать свой собственный массив путей, который можно отслеживать, но при этом вы можете иметь только один
.navigationDestination
на одном уровне в приложении (по крайней мере, как я понял, пока пробовал). Поскольку мне нужно иметь несколько уровней представления в моем приложении с несколькими.navigationDestination
, я вынужден использовать новыйNavigationPath
, поскольку это единственный способ хранить несколько типов объектов маршрутизации в пути.