SwiftUI - List / ForEach 与 NavigationLink 和 isActive 结合使用时无法正常工作
SwiftUI - List / ForEach in combination with NavigationLink and isActive doesn't work properly
我正在尝试在 SwiftUI 的列表或 ForEach 循环中执行 NavigationLink。不幸的是,我遇到了一个非常奇怪的行为(例如,当点击 Leo 时它打开了 Karl,打开 Max 也指向 Karl)。
我已经发现它与 NavigationLink 中的“isActive”属性有关。不幸的是,我需要它来实现这里的行为:https://i.stack.imgur.com/g0BFz.gif which is also asked here SwiftUI - Nested NavigationView: Go back to root.
我也尝试过使用选择和标签属性,但我无法实现“返回根”机制。
示例如下:
import SwiftUI
struct Model: Equatable, Hashable {
var userId: String
var firstName: String
var lastName: String
}
struct ContentView: View {
@State var navigationViewIsActive: Bool = false
var myModelArray: [Model] = [
Model(userId: "27e880a9-54c5-4da1-afff-05b4584b1d2f", firstName: "Leo", lastName: "Test"),
Model(userId: "1050412a-cb12-4160-b7e4-2702ab8430c3", firstName: "Max", lastName: "Test"),
Model(userId: "1050412a-cb12-4160-b7e4-2702ab8430c3", firstName: "Karl", lastName: "Test")]
var body: some View {
NavigationView {
List(myModelArray, id: \.self) { model in
NavigationLink(destination: secondView(firstName: model.firstName), isActive: $navigationViewIsActive){ Text(model.firstName) }
}
.listStyle(PlainListStyle())
}
}
}
struct secondView: View {
@State var firstName: String
var body: some View {
NavigationView {
Text(firstName)
.padding()
}
}
}
谢谢!
在这种情况下您不需要 isActive,只需使用
List(myModelArray, id: \.self) { model in
NavigationLink(destination: secondView(firstName: model.firstName)) {
Text(model.firstName)
}
}
并且您还没有在第二个视图中使用 NavigationView,即。
struct secondView: View {
var firstName: String // you don't need state here as well
var body: some View {
Text(firstName)
.padding()
}
}
这是因为只使用了一个状态navigationViewIsActive
所以当你点击导航 link 时,值将变为 True
,所有 link 将是 active
这种情况的解决方案是这样的:
- 定义一个新的
State
来保存选定的模型值
- 你只需要一个
NavigationLink
,然后将其设为 Hidden
(将其放在 VStack
中)
- 在
List
中使用 Button
而不是 NavigationLink
- 单击
Button
时:首先更改 selectedModel
值,然后激活导航链接 (true)
喜欢下面的代码 (Tested with IOS 14
) :
import SwiftUI
struct Model: Equatable, Hashable {
var userId: String
var firstName: String
var lastName: String
}
struct ContentView: View {
@State var navigationViewIsActive: Bool = false
@State var selectedModel : Model? = nil
var myModelArray: [Model] = [
Model(userId: "27e880a9-54c5-4da1-afff-05b4584b1d2f", firstName: "Leo", lastName: "Test"),
Model(userId: "1050412a-cb12-4160-b7e4-2702ab8430c3", firstName: "Max", lastName: "Test"),
Model(userId: "1050412a-cb12-4160-b7e4-2702ab8430c3", firstName: "Karl", lastName: "Test")]
var body: some View {
NavigationView {
VStack {
VStack {
if selectedModel != nil {
NavigationLink(destination: SecondView(firstName: selectedModel!.firstName), isActive: $navigationViewIsActive){ EmptyView() }
}
}.hidden()
List(myModelArray, id: \.self) { model in
Button(action: {
self.selectedModel = model
self.navigationViewIsActive = true
}, label: {
Text(model.firstName)
})
}
.listStyle(PlainListStyle())
}
}
}
}
struct SecondView: View {
@State var firstName: String
var body: some View {
NavigationView {
Text(firstName)
.padding()
}
}
}
struct Test_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
PS : 我写了这个 : How to navigate with SwiftUI ,它会帮助你理解在 swiftUI
中导航的方式
我正在尝试在 SwiftUI 的列表或 ForEach 循环中执行 NavigationLink。不幸的是,我遇到了一个非常奇怪的行为(例如,当点击 Leo 时它打开了 Karl,打开 Max 也指向 Karl)。
我已经发现它与 NavigationLink 中的“isActive”属性有关。不幸的是,我需要它来实现这里的行为:https://i.stack.imgur.com/g0BFz.gif which is also asked here SwiftUI - Nested NavigationView: Go back to root.
我也尝试过使用选择和标签属性,但我无法实现“返回根”机制。
示例如下:
import SwiftUI
struct Model: Equatable, Hashable {
var userId: String
var firstName: String
var lastName: String
}
struct ContentView: View {
@State var navigationViewIsActive: Bool = false
var myModelArray: [Model] = [
Model(userId: "27e880a9-54c5-4da1-afff-05b4584b1d2f", firstName: "Leo", lastName: "Test"),
Model(userId: "1050412a-cb12-4160-b7e4-2702ab8430c3", firstName: "Max", lastName: "Test"),
Model(userId: "1050412a-cb12-4160-b7e4-2702ab8430c3", firstName: "Karl", lastName: "Test")]
var body: some View {
NavigationView {
List(myModelArray, id: \.self) { model in
NavigationLink(destination: secondView(firstName: model.firstName), isActive: $navigationViewIsActive){ Text(model.firstName) }
}
.listStyle(PlainListStyle())
}
}
}
struct secondView: View {
@State var firstName: String
var body: some View {
NavigationView {
Text(firstName)
.padding()
}
}
}
谢谢!
在这种情况下您不需要 isActive,只需使用
List(myModelArray, id: \.self) { model in
NavigationLink(destination: secondView(firstName: model.firstName)) {
Text(model.firstName)
}
}
并且您还没有在第二个视图中使用 NavigationView,即。
struct secondView: View {
var firstName: String // you don't need state here as well
var body: some View {
Text(firstName)
.padding()
}
}
这是因为只使用了一个状态navigationViewIsActive
所以当你点击导航 link 时,值将变为 True
,所有 link 将是 active
这种情况的解决方案是这样的:
- 定义一个新的
State
来保存选定的模型值 - 你只需要一个
NavigationLink
,然后将其设为Hidden
(将其放在VStack
中) - 在
List
中使用Button
而不是NavigationLink
- 单击
Button
时:首先更改selectedModel
值,然后激活导航链接 (true)
喜欢下面的代码 (Tested with IOS 14
) :
import SwiftUI
struct Model: Equatable, Hashable {
var userId: String
var firstName: String
var lastName: String
}
struct ContentView: View {
@State var navigationViewIsActive: Bool = false
@State var selectedModel : Model? = nil
var myModelArray: [Model] = [
Model(userId: "27e880a9-54c5-4da1-afff-05b4584b1d2f", firstName: "Leo", lastName: "Test"),
Model(userId: "1050412a-cb12-4160-b7e4-2702ab8430c3", firstName: "Max", lastName: "Test"),
Model(userId: "1050412a-cb12-4160-b7e4-2702ab8430c3", firstName: "Karl", lastName: "Test")]
var body: some View {
NavigationView {
VStack {
VStack {
if selectedModel != nil {
NavigationLink(destination: SecondView(firstName: selectedModel!.firstName), isActive: $navigationViewIsActive){ EmptyView() }
}
}.hidden()
List(myModelArray, id: \.self) { model in
Button(action: {
self.selectedModel = model
self.navigationViewIsActive = true
}, label: {
Text(model.firstName)
})
}
.listStyle(PlainListStyle())
}
}
}
}
struct SecondView: View {
@State var firstName: String
var body: some View {
NavigationView {
Text(firstName)
.padding()
}
}
}
struct Test_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
PS : 我写了这个 : How to navigate with SwiftUI ,它会帮助你理解在 swiftUI
中导航的方式