0

我看到这个问题,Form / NavigationLink 设置似乎停止传递有关更改的数据。

预期行为:当您选择不同的食物时,复选标记应该会更新。
观察到的行为:您可以看到最喜欢的食物在 NavigationLink 目的地之外发生变化,但在内部却没有。

此设置反映了一个动态应用程序,其中 ForEach 用于根据父数据在表单中显示各种 NavigationLink。奇怪的是,如果你用 VStack 替换 Form,这会起作用,所以我很好奇为什么它没有更新。

我附上了两个最小设置示例项目,它们复制了这个问题,其中 NavigationLink 的目标在数据更改时没有收到更新。一种具有绑定,一种具有更简单的传递属性。

带绑定的示例项目 #1 - Dropbox
不带绑定的示例项目 #2 - Dropbox

代码#1:

//
//  ContentView.swift
//  Form Updating Example
//
//  Created by Sahand Nayebaziz on 12/10/20.
//

import SwiftUI

struct ContentView: View {
    @State var isPresentingMainView = false
    @State var favoriteFood: FoodType = .bagel
    
    var body: some View {
        VStack {
            Button(action: { isPresentingMainView = true }, label: {
                Text("Present Main View")
            })
        }
        .fullScreenCover(isPresented: $isPresentingMainView) {
            MainView(favoriteFood: $favoriteFood)
        }
    }
}

struct MainView: View {
    @Binding var favoriteFood: FoodType
    
    var body: some View {
        NavigationView {
            HStack {
                Spacer()
                Text(favoriteFood.emoji)
                    .font(.title)
                    .foregroundColor(.secondary)
                Spacer()
                NavigationView {
                    Form {
                        List {
                            ForEach(["SomethingRepresentingShowingFood"], id: \.self) { _ in
                                NavigationLink(
                                    destination: makeDetail(),
                                    label: {
                                        Text("Food Randomizer")
                                    })
                            }
                        }
                    }
                }
                .navigationViewStyle(StackNavigationViewStyle())
                .frame(maxWidth: 350)
            }
            .navigationTitle("Main")
            .navigationBarTitleDisplayMode(.inline)
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
    
    func makeDetail() -> some View {
        Form {
            ForEach(FoodType.allCases) { foodType in
                Button(action: { favoriteFood = foodType }, label: {
                    HStack {
                        Text(foodType.emoji)
                        Spacer()
                        if favoriteFood == foodType {
                            Image(systemName: "checkmark")
                        }
                    }
                })
            }
        }
    }
}

enum FoodType: String, Identifiable, CaseIterable {
    case bagel, pizza, broccoli
    
    var id: String { rawValue }
    
    var emoji: String {
        switch self {
        case .bagel: return ""
        case .pizza: return ""
        case .broccoli: return ""
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
            MainView(favoriteFood: .constant(.bagel))
            MainView(favoriteFood: .constant(.bagel))
                .makeDetail()
        }
    }
}

代码#2:

//
//  ContentView.swift
//  Form Updating Example
//
//  Created by Sahand Nayebaziz on 12/10/20.
//

import SwiftUI

struct ContentView: View {
    @State var isPresentingMainView = false
    @State var favoriteFood: FoodType = .bagel
    
    var body: some View {
        VStack {
            Button(action: { isPresentingMainView = true }, label: {
                Text("Present Main View")
            })
        }
        .fullScreenCover(isPresented: $isPresentingMainView) {
            MainView(currentFavoriteFood: favoriteFood, onUpdateFavoriteFood: { favoriteFood = $0 })
        }
    }
}

struct MainView: View {
    let currentFavoriteFood: FoodType
    let onUpdateFavoriteFood: (FoodType) -> Void
    
    var body: some View {
        NavigationView {
            HStack {
                Spacer()
                Text(currentFavoriteFood.emoji)
                    .font(.title)
                    .foregroundColor(.secondary)
                Spacer()
                NavigationView {
                    Form {
                        List {
                            ForEach(["SomethingRepresentingShowingFood"], id: \.self) { _ in
                                NavigationLink(
                                    destination: makeDetail(),
                                    label: {
                                        Text("Food Randomizer")
                                    })
                            }
                        }
                    }
                }
                .navigationViewStyle(StackNavigationViewStyle())
                .frame(maxWidth: 350)
            }
            .navigationTitle("Main")
            .navigationBarTitleDisplayMode(.inline)
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
    
    func makeDetail() -> some View {
        Form {
            ForEach(FoodType.allCases) { foodType in
                Button(action: { onUpdateFavoriteFood(foodType) }, label: {
                    HStack {
                        Text(foodType.emoji)
                        Spacer()
                        if currentFavoriteFood == foodType {
                            Image(systemName: "checkmark")
                        }
                    }
                })
            }
        }
    }
}

enum FoodType: String, Identifiable, CaseIterable {
    case bagel, pizza, broccoli
    
    var id: String { rawValue }
    
    var emoji: String {
        switch self {
        case .bagel: return ""
        case .pizza: return ""
        case .broccoli: return ""
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
            MainView(currentFavoriteFood: .bagel, onUpdateFavoriteFood: { _ in })
            MainView(currentFavoriteFood: .bagel, onUpdateFavoriteFood: { _ in })
                .makeDetail()
        }
    }
}
4

0 回答 0