根据条件显示 NavigationLink 并在目的地内编辑值

Posted

技术标签:

【中文标题】根据条件显示 NavigationLink 并在目的地内编辑值【英文标题】:Show NavigationLink based on condition and having value edited inside the destination 【发布时间】:2020-04-08 05:48:20 【问题描述】:

我的StudentStore 有一个 ForEach 循环,如果isFavorite 字段为真,我只想在我的列表中显示它们。

问题是当我在SecondView 中编辑isFavorite 的值时,由于ContentView 中的if 语句,它会回到ContentView

我希望在我返回 ContentView 时更新列表,而不是立即更新它导致它返回到原始页面。

当我在寻找解决方案时,我想到了这个:

阅读整个线程,以为您在问是否可以有条件地隐藏 NavigationView,然后想:“这听起来很混乱……” 来源:https://www.reddit.com/r/SwiftUI/comments/e2wn09/make_navigationlink_conditional_based_on_bool/

还有人可以解决这个问题吗?为什么有条件地隐藏NavigationView 是个坏主意?

型号

import SwiftUI

struct StudentItem: Identifiable 
    var id = UUID()
    var name: String
    var isFavorite: Bool

    init(name: String, isFavorite: Bool) 
        self.name = name
        self.isFavorite = isFavorite
    


class StudentStore: ObservableObject 
    @Published var StudentStore: [StudentItem]

    init(StudentStore: [StudentItem])
        self.StudentStore = StudentStore
    

主视图

struct ContentView: View 
    @ObservedObject var studentStore = StudentStore(StudentStore: [StudentItem(name: "Stephen", isFavorite: true),
                                                                   StudentItem(name: "Jay", isFavorite: true),
                                                                   StudentItem(name: "Isaac", isFavorite: true),
                                                                   StudentItem(name: "Talha", isFavorite: true),
                                                                   StudentItem(name: "John", isFavorite: true),
                                                                   StudentItem(name: "Matt", isFavorite: true),
                                                                   StudentItem(name: "Leo", isFavorite: true)])

    var body: some View 
        NavigationView 
            List 
                ForEach(studentStore.StudentStore.indices, id: \.self)  index in
                    Group 
                        if self.studentStore.StudentStore[index].isFavorite == true 
                            NavigationLink(destination: SecondView(student: self.$studentStore.StudentStore[index])) 
                                HStack 
                                    Text(self.studentStore.StudentStore[index].name)
                                    Image(systemName: self.studentStore.StudentStore[index].isFavorite ? "star.fill" : "star")
                                
                            
                        
                    
                
            
        
    

子视图

struct SecondView: View 
    @Binding var student: StudentItem

    var body: some View 
        Button(action: 
            self.student.isFavorite.toggle()
        ) 
            Image(systemName: student.isFavorite ? "star.fill" : "star")
        
    

【问题讨论】:

【参考方案1】:

问题是有道理的,它是一个 Binded 值。根据绑定,该人SecondView 的导航在技术上不再存在。

您可以为SecondView 创建一个本地化的State,将您的图像和按钮设置为使用该属性,然后在导航返回时使用onDisappear 更新StudentItem

struct SecondView: View 
    @Binding var student: StudentItem
    @State var isFavorite: Bool = true

    var body: some View 
        Button(action: 
            self.isFavorite.toggle()
        ) 
            Image(systemName: self.isFavorite ? "star.fill" : "star")
        .onDisappear 
            self.student.isFavorite = self.isFavorite
        
    

以上内容将适用于您的其余代码。

至于不使用if 声明,我有点明白。对我来说,我想遍历我知道我想要包含的值。并不是说这是完美的,但您可以在进入之前过滤列表,然后调用 StudentItem 的 Bindable 引用以传递到 SecondView。一定要让 StudentItem Hashable 这个工作:

var body: some View 
        NavigationView 
            List 
                ForEach(studentStore.StudentStore.filter($0.isFavorite == true), id: \.self)  student in
                    Group 
                        NavigationLink(destination: SecondView(student: self.$studentStore.StudentStore[self.studentStore.StudentStore.firstIndex(of: student)!])) 
                                HStack 
                                    Text(student.name)
                                    Image(systemName: student.isFavorite ? "star.fill" : "star")
                                
                            
                        
                
            
        
    

【讨论】:

这会产生更理想的结果,但我希望在list 可见之前进行转换。 我听到了。另一种解决方案是制作自己的后退按钮,类似于解决方案here。这样,您可以在调用解除之前专门更新 Bindable 对象。需要注意的是,我不确定您是否仍想在将值更新为 false 后调用解雇,因为这可能会像根本问题一样“自动解雇”,哈哈。

以上是关于根据条件显示 NavigationLink 并在目的地内编辑值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI 的文本块中嵌入 NavigationLink?

从目标视图返回时,SwiftUI NavigationLink 显示为突出显示

表单/表格中的 SwiftUI 多个 NavigationLink - 条目保持突出显示

NavigationLink 显示为灰色且不执行任何操作 [重复]

在 SwiftUI 中显示 NavigationLink 时过渡动画消失了

在 NavigationLink 的嵌套 NavigationView 中列出核心数据对象的正确方法