SwiftUI 选择器中所选选项的值不会更新视图
Value of Selected Option From a SwiftUI Picker does not Update the View
我在 SwiftUI 应用程序中有以下内容。基本上我有一些我想在整个应用程序中使用的设置(设置 class)。我有一个设置视图,显示了一个选择器 select 其中一个设置的值。而应用程序的其他视图只会使用设置的当前设置值。以下设置的工作原理是在 ContentView 中我看到 firstLevel
设置的正确值。但问题是在 SettingsView 中,我认为因为 selectedFirstLevel
不是 @State,所以它的正确值没有显示在我导航到 select even
或 [=16= 的选择器上] (奇怪的是,第一次是正确的)。此 selection 已正确传送到 ContentView,但未在 SettingsView 上正确显示。我该如何解决这个问题?
Settings.swift
import Foundation
class Settings: ObservableObject {
static let shared: Settings = Settings()
@Published var firstLevel: FirstLevel = .even
}
enum FirstLevel: String, CaseIterable, Identifiable {
case even
case odd
var id: String { self.rawValue }
}
ContentView.swift
import SwiftUI
struct ContentView: View {
@State private var showSettings: Bool = false
@ObservedObject var settings = Settings.shared
var body: some View {
VStack {
SettingsButton(showSettings: $showSettings, settings: settings)
Text(settings.firstLevel.id)
.padding()
}
}
}
struct SettingsButton: View {
@Binding var showSettings: Bool
var settings: Settings
var firstLevel: Binding<FirstLevel> {
return Binding<FirstLevel>(
get: {
return self.settings.firstLevel
}) { newFirstLevel in
self.settings.firstLevel = newFirstLevel
}
}
var body: some View {
Button(action: { self.showSettings = true }) {
Image(systemName: "gear").imageScale(.large)
}
.sheet(isPresented: $showSettings) {
SettingsView(selectedFirstLevel: self.firstLevel)
}
}
}
SettingsView.swift
import SwiftUI
struct SettingsView: View {
@Binding var selectedFirstLevel: FirstLevel
var body: some View {
NavigationView {
Form {
Picker("First Level", selection: $selectedFirstLevel) {
ForEach(FirstLevel.allCases) { level in
Text(level.rawValue).tag(level)
}
}
}
.navigationBarTitle("Settings", displayMode: .inline)
}
}
}
它看起来过于复杂,而且绑定作为不同视图层次结构之间的通信是不可靠的(在你的情况下是 sheet)。
这里是经过简化和有效的变体。测试 Xcode 12 / iOS 14.
struct ContentView: View {
@ObservedObject var settings = FLevelSettings.shared
var body: some View {
VStack {
SettingsButton(settings: settings)
Text(settings.firstLevel.id)
.padding()
}
}
}
struct SettingsButton: View {
@State private var showSettings: Bool = false
var settings: FLevelSettings
var body: some View {
Button(action: { self.showSettings = true }) {
Image(systemName: "gear").imageScale(.large)
}
.sheet(isPresented: $showSettings) {
FLevelSettingsView(settings: self.settings)
}
}
}
struct FLevelSettingsView: View {
@ObservedObject var settings: FLevelSettings
var body: some View {
NavigationView {
Form {
Picker("First Level", selection: $settings.firstLevel) {
ForEach(FirstLevel.allCases) { level in
Text(level.rawValue).tag(level)
}
}
}
.navigationBarTitle("Settings", displayMode: .inline)
}
}
}
注意:由于 FLevelSettings.shared
的存在,如果你愿意,它可以更加简化,所以你可以直接在 FLevelSettingsView
中使用它。以防万一
我在 SwiftUI 应用程序中有以下内容。基本上我有一些我想在整个应用程序中使用的设置(设置 class)。我有一个设置视图,显示了一个选择器 select 其中一个设置的值。而应用程序的其他视图只会使用设置的当前设置值。以下设置的工作原理是在 ContentView 中我看到 firstLevel
设置的正确值。但问题是在 SettingsView 中,我认为因为 selectedFirstLevel
不是 @State,所以它的正确值没有显示在我导航到 select even
或 [=16= 的选择器上] (奇怪的是,第一次是正确的)。此 selection 已正确传送到 ContentView,但未在 SettingsView 上正确显示。我该如何解决这个问题?
Settings.swift
import Foundation
class Settings: ObservableObject {
static let shared: Settings = Settings()
@Published var firstLevel: FirstLevel = .even
}
enum FirstLevel: String, CaseIterable, Identifiable {
case even
case odd
var id: String { self.rawValue }
}
ContentView.swift
import SwiftUI
struct ContentView: View {
@State private var showSettings: Bool = false
@ObservedObject var settings = Settings.shared
var body: some View {
VStack {
SettingsButton(showSettings: $showSettings, settings: settings)
Text(settings.firstLevel.id)
.padding()
}
}
}
struct SettingsButton: View {
@Binding var showSettings: Bool
var settings: Settings
var firstLevel: Binding<FirstLevel> {
return Binding<FirstLevel>(
get: {
return self.settings.firstLevel
}) { newFirstLevel in
self.settings.firstLevel = newFirstLevel
}
}
var body: some View {
Button(action: { self.showSettings = true }) {
Image(systemName: "gear").imageScale(.large)
}
.sheet(isPresented: $showSettings) {
SettingsView(selectedFirstLevel: self.firstLevel)
}
}
}
SettingsView.swift
import SwiftUI
struct SettingsView: View {
@Binding var selectedFirstLevel: FirstLevel
var body: some View {
NavigationView {
Form {
Picker("First Level", selection: $selectedFirstLevel) {
ForEach(FirstLevel.allCases) { level in
Text(level.rawValue).tag(level)
}
}
}
.navigationBarTitle("Settings", displayMode: .inline)
}
}
}
它看起来过于复杂,而且绑定作为不同视图层次结构之间的通信是不可靠的(在你的情况下是 sheet)。
这里是经过简化和有效的变体。测试 Xcode 12 / iOS 14.
struct ContentView: View {
@ObservedObject var settings = FLevelSettings.shared
var body: some View {
VStack {
SettingsButton(settings: settings)
Text(settings.firstLevel.id)
.padding()
}
}
}
struct SettingsButton: View {
@State private var showSettings: Bool = false
var settings: FLevelSettings
var body: some View {
Button(action: { self.showSettings = true }) {
Image(systemName: "gear").imageScale(.large)
}
.sheet(isPresented: $showSettings) {
FLevelSettingsView(settings: self.settings)
}
}
}
struct FLevelSettingsView: View {
@ObservedObject var settings: FLevelSettings
var body: some View {
NavigationView {
Form {
Picker("First Level", selection: $settings.firstLevel) {
ForEach(FirstLevel.allCases) { level in
Text(level.rawValue).tag(level)
}
}
}
.navigationBarTitle("Settings", displayMode: .inline)
}
}
}
注意:由于 FLevelSettings.shared
的存在,如果你愿意,它可以更加简化,所以你可以直接在 FLevelSettingsView
中使用它。以防万一