SwiftUI:@State 属性不会在没有奇怪的解决方法的情况下更新

问题描述

我遇到了一个奇怪的行为,@State 属性在另一个视图中更改后没有在其原始视图中正确更新。我使用的是 Xcode 12.3 和 iOS 14。

发生的情况是@State“会话”基于值的项目和@State“流”基于值的项目作为绑定参数发送到另一个视图。当一个按钮在那里被点击时,它会改变它们的值,并且原始视图中的 fullScreenCover 调用应该从 switch 语句获得正确的视图以显示在流程中的下一个。但是,除非我包含一个 onChange 修饰符来查找两个 @State 属性中的任何一个中的更改,否则该 switch 语句中的“会话”项为零。 onChange 调用中无需包含任何代码即可实现此效果

我对 SwiftUI 还是比较陌生(尽管在 iOS 和 Mac 开发方面经验丰富)。但这让我很困惑。我不明白为什么它没有按预期工作,也不明白为什么添加一个空的 onChange 处理程序使它工作。

如果您想亲自体验,这里是组装一个简单演示项目的代码

SortedSet

解决方法

class ObservationSession: //Codable,//implement Codable manually
    ObservableObject {
    public let id: UUID
    //This allows you to observe the individual variable
    @Published public var name: String
    
    public init(name: String) {
        self.name = name
        self.id = UUID()
    }
    
}

struct SessionListModals {
    enum Flow: Identifiable {
        case configuration
        case observation
        case newSession
        
        var id: Flow { self }
    }
}

// ContentView
class ContentViewModel: ObservableObject {
    @Published var mutableSession: ObservationSession?
    
}
struct ContentView: View {
    //State stores the entire object and observes it as a whole it does not individually observe its variables that is why .onChange works
    @StateObject var vm: ContentView3Model = ContentView3Model()
    @State private var flow: SessionListModals.Flow?
    var body: some View {
        VStack {
            Button("New Session",action: {
                //Since you want to change it programatically you have to put them in another object
                vm.mutableSession = ObservationSession(name: "")
                flow = .newSession
            })
            .padding()
        }
        .fullScreenCover(item: $flow) {
            viewForFlow($0)
        }
    }
    
    @ViewBuilder private func viewForFlow(_ flow: SessionListModals.Flow) -> some View {
        switch flow {
        case .newSession:
            // MARK: - Show New Session View
            NavigationView {
                NewSessionView(session: $vm.mutableSession,flow: $flow)
                    .navigationTitle("Create a session")
                    .navigationBarItems(leading: Button("Cancel",action: {
                        self.flow = nil
                    }))
            }
        case .observation:
            // MARK: - Show RecordingView
            NavigationView {
                let name = vm.mutableSession?.name ?? "Unnamed session"
                RecordingView(sessionName: name)
                    .navigationBarItems(leading: Button("Close",action: {
                        self.flow = nil
                    }))
            }
        default:
            NavigationView {
                EmptyView()
                    .navigationBarItems(leading: Button("Close",action: {
                        self.flow = nil
                    }))
            }
        }
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...