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