iOS 15:导航 link 再次弹出
iOS 15: Navigation link popping out, again
在过去的几个月里,许多开发人员报告 NavigationLinks 意外弹出,并且已经发布了一些解决方法,包括添加另一个空 link 和添加 .navigationViewStyle(StackNavigationViewStyle()) 到导航视图。
在这里,我想演示另一种意外弹出NavigationLink的情况:
当子视图有两级时,即parentView > childLevel1 > childLevel2 ,childLevel2修改childLevel1,然后从level 2回到level 1后弹出level 1,显示parentView
我已经提交了一个错误报告,但从那以后就没有收到苹果的消息了。 None 的已知解决方法似乎有效。有人知道该怎么做吗?等待 iOS 15.1?
下面是我的代码(iPhone 应用程序)。在父视图中,有一个接受订单的人员列表。在 childLevel1 中,显示来自特定人的所有订单。可以通过单击修改每个订单,这会导致 childLevel2。在 childLevel2 中,有几个选项可用(这里为了简洁只显示一个),这就是为什么用户应该通过“<返回”离开 childLevel2 的原因。
import SwiftUI
struct Person: Identifiable, Hashable {
let id: Int
let name: String
var orders: [Order]
}
struct Pastry: Identifiable, Hashable {
let id: Int
let name: String
}
struct Order: Hashable {
var paId: Int
var n: Int // used only in the real code
}
class Data : ObservableObject {
init() {
pastries = [
Pastry(id: 0, name: "Prezel"),
Pastry(id: 1, name: "Donut"),
Pastry(id: 2, name: "bagel"),
Pastry(id: 3, name: "cheese cake"),
]
persons = [
Person(id: 0, name: "Alice", orders: [Order(paId: 1, n: 1)]),
Person(id: 1, name: "Bob", orders: [Order(paId: 2, n: 1), Order(paId: 3, n: 1)])
]
activePersonsIds = [0, 1]
}
@Published var activePersonsIds: [Int] = []
@Published var persons: [Person] = []
@Published var pastries: [Pastry]
@Published var latestOrder = Order(paId: 0, n: 1)
lazy var pastryName: (Int) -> String = { (paId: Int) -> String in
if self.pastries.first(where: { [=12=].id == paId }) == nil {
return "undefined pastryId " + String(paId)
}
return self.pastries.first(where: { [=12=].id == paId })!.name
}
var activePersons : [Person] {
return activePersonsIds.compactMap {id in persons.first(where: {[=12=].id == id})}
}
}
@main
struct Bretzel_ProApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@Environment(\.colorScheme) var colorScheme
@StateObject var data = Data()
var body: some View {
TabView1(data: data)
// in the real code, there are more tabs
}
}
struct TabView1: View {
@StateObject var data: Data
var body: some View {
NavigationView {
List {
ForEach(data.activePersons, id: \.self) { person in
NavigationLink(
destination: EditPerson(data: data, psId: person.id),
label: {
VStack (alignment: .leading) {
Text(person.name)
}
}
)
}
}
.listStyle(PlainListStyle())
.navigationTitle("Orders")
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
struct EditPerson: View {
@ObservedObject var data: Data
var psId: Int
var body: some View {
let pindex: Int = data.persons.firstIndex(where: { [=12=].id == psId })!
let p: Person = data.persons[pindex]
List() {
ForEach (0...p.orders.count-1, id: \.self) { loop in
Section(header:
HStack() {
Text("BESTELLUNG " + String(loop+1))
}
) {
EPSubview1(data: data, psId: psId, loop: loop)
}
}
}.navigationTitle(p.name)
.listStyle(InsetGroupedListStyle())
}
}
struct EPSubview1: View {
@ObservedObject var data: Data
var psId: Int
var loop: Int
var body: some View {
let pindex: Int = data.persons.firstIndex(where: { [=12=].id == psId })!
let p: Person = data.persons[pindex]
let o1: Order = p.orders[loop]
NavigationLink(
destination: SelectPastry(data: data)
.onAppear() {
data.latestOrder.paId = o1.paId
}
.onDisappear() {
data.persons[pindex].orders[loop].paId = data.latestOrder.paId
},
label: {
VStack(alignment: .leading) {
Text(String(o1.n) + " x " + data.pastryName(o1.paId))
}
}
)
}
}
struct SelectPastry: View {
@ObservedObject var data : Data
var body: some View {
VStack {
List {
ForEach(data.pastries, id: \.self) {pastry in
Button(action: {
data.latestOrder.paId = pastry.id
}) {
Text(pastry.name)
.foregroundColor(data.latestOrder.paId == pastry.id ? .primary : .secondary)
}
}
}.listStyle(PlainListStyle())
}
}
}
问题是你的ForEach
。尽管 Person
符合 Identifiable
,但您正在使用 \.self
来识别数据。因此,每当 Person
的一个方面发生变化时,self
.
的值也会发生变化
相反,只需使用此表单,它使用 Identifiable
出售的 id
:
ForEach(data.activePersons) { person in
相当于:
ForEach(data.activePersons, id: \.id) { person in
在过去的几个月里,许多开发人员报告 NavigationLinks 意外弹出,并且已经发布了一些解决方法,包括添加另一个空 link 和添加 .navigationViewStyle(StackNavigationViewStyle()) 到导航视图。
在这里,我想演示另一种意外弹出NavigationLink的情况:
当子视图有两级时,即parentView > childLevel1 > childLevel2 ,childLevel2修改childLevel1,然后从level 2回到level 1后弹出level 1,显示parentView
我已经提交了一个错误报告,但从那以后就没有收到苹果的消息了。 None 的已知解决方法似乎有效。有人知道该怎么做吗?等待 iOS 15.1?
下面是我的代码(iPhone 应用程序)。在父视图中,有一个接受订单的人员列表。在 childLevel1 中,显示来自特定人的所有订单。可以通过单击修改每个订单,这会导致 childLevel2。在 childLevel2 中,有几个选项可用(这里为了简洁只显示一个),这就是为什么用户应该通过“<返回”离开 childLevel2 的原因。
import SwiftUI
struct Person: Identifiable, Hashable {
let id: Int
let name: String
var orders: [Order]
}
struct Pastry: Identifiable, Hashable {
let id: Int
let name: String
}
struct Order: Hashable {
var paId: Int
var n: Int // used only in the real code
}
class Data : ObservableObject {
init() {
pastries = [
Pastry(id: 0, name: "Prezel"),
Pastry(id: 1, name: "Donut"),
Pastry(id: 2, name: "bagel"),
Pastry(id: 3, name: "cheese cake"),
]
persons = [
Person(id: 0, name: "Alice", orders: [Order(paId: 1, n: 1)]),
Person(id: 1, name: "Bob", orders: [Order(paId: 2, n: 1), Order(paId: 3, n: 1)])
]
activePersonsIds = [0, 1]
}
@Published var activePersonsIds: [Int] = []
@Published var persons: [Person] = []
@Published var pastries: [Pastry]
@Published var latestOrder = Order(paId: 0, n: 1)
lazy var pastryName: (Int) -> String = { (paId: Int) -> String in
if self.pastries.first(where: { [=12=].id == paId }) == nil {
return "undefined pastryId " + String(paId)
}
return self.pastries.first(where: { [=12=].id == paId })!.name
}
var activePersons : [Person] {
return activePersonsIds.compactMap {id in persons.first(where: {[=12=].id == id})}
}
}
@main
struct Bretzel_ProApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@Environment(\.colorScheme) var colorScheme
@StateObject var data = Data()
var body: some View {
TabView1(data: data)
// in the real code, there are more tabs
}
}
struct TabView1: View {
@StateObject var data: Data
var body: some View {
NavigationView {
List {
ForEach(data.activePersons, id: \.self) { person in
NavigationLink(
destination: EditPerson(data: data, psId: person.id),
label: {
VStack (alignment: .leading) {
Text(person.name)
}
}
)
}
}
.listStyle(PlainListStyle())
.navigationTitle("Orders")
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
struct EditPerson: View {
@ObservedObject var data: Data
var psId: Int
var body: some View {
let pindex: Int = data.persons.firstIndex(where: { [=12=].id == psId })!
let p: Person = data.persons[pindex]
List() {
ForEach (0...p.orders.count-1, id: \.self) { loop in
Section(header:
HStack() {
Text("BESTELLUNG " + String(loop+1))
}
) {
EPSubview1(data: data, psId: psId, loop: loop)
}
}
}.navigationTitle(p.name)
.listStyle(InsetGroupedListStyle())
}
}
struct EPSubview1: View {
@ObservedObject var data: Data
var psId: Int
var loop: Int
var body: some View {
let pindex: Int = data.persons.firstIndex(where: { [=12=].id == psId })!
let p: Person = data.persons[pindex]
let o1: Order = p.orders[loop]
NavigationLink(
destination: SelectPastry(data: data)
.onAppear() {
data.latestOrder.paId = o1.paId
}
.onDisappear() {
data.persons[pindex].orders[loop].paId = data.latestOrder.paId
},
label: {
VStack(alignment: .leading) {
Text(String(o1.n) + " x " + data.pastryName(o1.paId))
}
}
)
}
}
struct SelectPastry: View {
@ObservedObject var data : Data
var body: some View {
VStack {
List {
ForEach(data.pastries, id: \.self) {pastry in
Button(action: {
data.latestOrder.paId = pastry.id
}) {
Text(pastry.name)
.foregroundColor(data.latestOrder.paId == pastry.id ? .primary : .secondary)
}
}
}.listStyle(PlainListStyle())
}
}
}
问题是你的ForEach
。尽管 Person
符合 Identifiable
,但您正在使用 \.self
来识别数据。因此,每当 Person
的一个方面发生变化时,self
.
相反,只需使用此表单,它使用 Identifiable
出售的 id
:
ForEach(data.activePersons) { person in
相当于:
ForEach(data.activePersons, id: \.id) { person in