SwiftUI - 导航时视图是否保持活动状态?
SwiftUI - Are views kept alive while navigating?
我在使用 NavigationLinks 和 ObservableObject 时遇到错误。我不太明白为什么,因为我不明白在导航时视图和数据发生了什么。这是一些伪代码来说明问题:
class Settings: ObservableObject {
@Published var data: [Int] = [0, 1, 2, 3, 4, 5]
}
struct ContentView: View {
@State var new_view: Bool = false
@ObservedObject var content_view_settings = Settings()
var body: some View {
NavigationView {
VStack {
Button(action: {
DeleteLastItem()
}) {
Text("Delete last item")
}
Button(action: {
self.new_view = true
}) {
Text("New View")
}
NavigationLink(destination: NewView(new_view_settings: content_view_settings), isActive: $new_view) {
EmptyView()
}
}
}
}
}
struct NewView: View {
@ObservedObject var new_view_settings: Settings
@State var index = -1
var body: some View {
VStack {
Button(action: {
self.index = self.new_view_settings.count - 1
}) {
Text("change index")
}
if self.index > -1 {
Text("\(self.new_view_settings.data[index])")
}
}
}
}
问题描述是这样的:
我有一个带有 ObservedObject 的视图,我在导航时将其传递给后续视图。该子视图访问数组的最后一个元素,但它仅在通过单击按钮验证索引变量后才执行此操作。然后仅在验证索引后才呈现文本。
现在,假设我验证了索引,因此在此示例中它等于 5。然后我导航回原始视图。如果我删除最后一个元素,索引 5 将不再有效。一旦删除最后一个元素,我就会收到无效索引错误并且模拟器崩溃。
但是假设我向后导航并且没有删除最后一个元素。然后当我向前导航时,索引变量被重置。
因为我遇到崩溃,这意味着视图仍然存在并且正在更新或其他东西,但是当我再次导航到它时,视图会重新加载。这是否意味着视图在再次初始化之前一直有效?这是人为的代码,但它本质上是我遇到的问题。我认为原始代码会有点难以理解。
Does this mean the view is alive until it gets initialized again?
是的,即使在您导航回父视图后视图可能仍然存在。
为了更好地理解正在发生的事情 运行 在 iPad 模拟器(最好是水平模式)上使用相同的代码。您会注意到 NavigationView
分为两部分:master 和 detail - 这样您就可以同时看到父项和子项立即查看。
现在,如果您根据问题执行相同的实验,您将看到子视图仍然存在,即使您向后导航也是如此。 iOS.
也是如此
防止这种情况的一种方法是检查数组中是否存在索引:
struct NewView: View {
@ObservedObject var new_view_settings: Settings
@State var index = -1
var body: some View {
VStack {
Button(action: {
//self.index = self.new_view_settings.count - 1
}) {
Text("change index")
}
// check if `index` is in array
if self.index > -1 && self.index < self.new_view_settings.data.count {
Text("\(self.new_view_settings.data[index])")
}
}
}
}
注意:通常我不建议在 SwiftUI 视图中处理索引 - 通常有更好的方法来传递数据。处理指数是 有风险的。
我在使用 NavigationLinks 和 ObservableObject 时遇到错误。我不太明白为什么,因为我不明白在导航时视图和数据发生了什么。这是一些伪代码来说明问题:
class Settings: ObservableObject {
@Published var data: [Int] = [0, 1, 2, 3, 4, 5]
}
struct ContentView: View {
@State var new_view: Bool = false
@ObservedObject var content_view_settings = Settings()
var body: some View {
NavigationView {
VStack {
Button(action: {
DeleteLastItem()
}) {
Text("Delete last item")
}
Button(action: {
self.new_view = true
}) {
Text("New View")
}
NavigationLink(destination: NewView(new_view_settings: content_view_settings), isActive: $new_view) {
EmptyView()
}
}
}
}
}
struct NewView: View {
@ObservedObject var new_view_settings: Settings
@State var index = -1
var body: some View {
VStack {
Button(action: {
self.index = self.new_view_settings.count - 1
}) {
Text("change index")
}
if self.index > -1 {
Text("\(self.new_view_settings.data[index])")
}
}
}
}
问题描述是这样的:
我有一个带有 ObservedObject 的视图,我在导航时将其传递给后续视图。该子视图访问数组的最后一个元素,但它仅在通过单击按钮验证索引变量后才执行此操作。然后仅在验证索引后才呈现文本。
现在,假设我验证了索引,因此在此示例中它等于 5。然后我导航回原始视图。如果我删除最后一个元素,索引 5 将不再有效。一旦删除最后一个元素,我就会收到无效索引错误并且模拟器崩溃。
但是假设我向后导航并且没有删除最后一个元素。然后当我向前导航时,索引变量被重置。
因为我遇到崩溃,这意味着视图仍然存在并且正在更新或其他东西,但是当我再次导航到它时,视图会重新加载。这是否意味着视图在再次初始化之前一直有效?这是人为的代码,但它本质上是我遇到的问题。我认为原始代码会有点难以理解。
Does this mean the view is alive until it gets initialized again?
是的,即使在您导航回父视图后视图可能仍然存在。
为了更好地理解正在发生的事情 运行 在 iPad 模拟器(最好是水平模式)上使用相同的代码。您会注意到 NavigationView
分为两部分:master 和 detail - 这样您就可以同时看到父项和子项立即查看。
现在,如果您根据问题执行相同的实验,您将看到子视图仍然存在,即使您向后导航也是如此。 iOS.
也是如此防止这种情况的一种方法是检查数组中是否存在索引:
struct NewView: View {
@ObservedObject var new_view_settings: Settings
@State var index = -1
var body: some View {
VStack {
Button(action: {
//self.index = self.new_view_settings.count - 1
}) {
Text("change index")
}
// check if `index` is in array
if self.index > -1 && self.index < self.new_view_settings.data.count {
Text("\(self.new_view_settings.data[index])")
}
}
}
}
注意:通常我不建议在 SwiftUI 视图中处理索引 - 通常有更好的方法来传递数据。处理指数是 有风险的。