【问题标题】:View only updated by EnvironmentObject after App-restart应用重启后仅由 EnvironmentObject 更新的视图
【发布时间】:2020-11-17 22:58:06
【问题描述】:

我有这种奇怪的行为,我已经尝试修复了好几个小时:

当 EnvironmentObject UserSettings 发生变化时,我的一个观点没有被更新。虽然如果我完全重新启动应用程序,新值将按原样使用。

这是一个简短的 gif:https://s8.gifyu.com/images/Screen-Recording-2020-11-17-at-15.36.07.gif

所以值被正确存储并且视图正在访问正确的实例,但由于它是@Published,我希望它会像在另一个视图中一样立即更改。知道我做错了什么吗?

我构建了一个显示相同行为的小应用程序:

UserSettings.swift

import SwiftUI

final class UserSettings: ObservableObject {
    
    @Published var colorSelection: Int {
        didSet {
            UserDefaults.standard.set(colorSelection, forKey: "colorSelection")
        }
    }
    
    @Published var qnh: Double {
        didSet {
            UserDefaults.standard.set(qnh, forKey: "qnh")
        }
    }
    
    @Published var offset: Double {
        didSet {
            UserDefaults.standard.set(offset, forKey: "offset")
        }
    }
    
    @Published var colors: Array<Color> {
        didSet {
            UserDefaults.standard.set(colors, forKey: "colors")
        }
    }
    
    init() {
        self.colorSelection = UserDefaults.standard.object(forKey: "colorSelection") as? Int ?? 0
        self.qnh = UserDefaults.standard.object(forKey: "qnh") as? Double ?? 1013.25
        self.offset = UserDefaults.standard.object(forKey: "offset") as? Double ?? 0
        self.colors = UserDefaults.standard.object(forKey: "colors") as? Array ?? [Color.green, Color.white, Color.red, Color.blue, Color.orange, Color.yellow, Color.pink, Color.purple, Color.black]
    }
}

TestApp.swift

import SwiftUI

@main
struct TestApp: App {
    @StateObject var userSettings = UserSettings()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(UserSettings())
        }
    }
}

ContentView.swift

import SwiftUI

struct ContentView: View {
    @EnvironmentObject var userSettings: UserSettings
    @State var view = 2
    
    var body: some View {
        TabView(selection: $view) {
            MainView()
                .environmentObject(UserSettings())
                .tabItem {Image(systemName: "location")}
                .tag(0)
            NavigationView {
                SettingsView()
                    .environmentObject(UserSettings())
                    .navigationTitle("Settings")
            }
            .tabItem {Image(systemName: "gearshape")}
            .tag(2)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(UserSettings())
    }
}

MainView.swift

import SwiftUI

struct MainView: View {
    @EnvironmentObject var userSettings: UserSettings
    
    var body: some View {
       Text("Test")
        .foregroundColor(userSettings.colors[userSettings.colorSelection])
    }
}

SettingsView.swift

import SwiftUI

struct SettingsView: View {
    @EnvironmentObject var userSettings: UserSettings
    @State private var selection: Int = 0
    private let colors = ["Green", "White", "Red", "Blue", "Orange", "Yellow", "Pink", "Purple", "Black"]
    
    var body: some View {
        Form {
            Section(header: Text("Customize")) {
                Picker(selection: $userSettings.colorSelection, label: Text("Font Color")) {
                    ForEach(0 ..< colors.count) {
                        Text(self.colors[$0]).foregroundColor(userSettings.colors[$0])
                    }.foregroundColor(userSettings.colors[userSettings.colorSelection])
                }
            }
        }
    }
}

【问题讨论】:

    标签: ios swiftui


    【解决方案1】:

    您正在创建 UserSetting 的新对象并将它们传递给子视图。您应该创建该对象并将其传递给子视图。

    在您的内容视图中

    struct ContentView: View {
        @EnvironmentObject var userSettings: UserSettings
        @State var view = 2
        
        var body: some View {
            TabView(selection: $view) {
                MainView()
                    .environmentObject(userSetting) //<< here pass the correct one
                    .tabItem {Image(systemName: "location")}
                    .tag(0)
                NavigationView {
                    SettingsView()
                        .environmentObject(userSetting) //<< here aswell
                        .navigationTitle("Settings")
                }
                .tabItem {Image(systemName: "gearshape")}
                .tag(2)
            }
        }
    }
    

    编辑:

    实际上它甚至更简单,因为您不必手动将其传递给子视图。只需声明

    @EnvironmentObject var userSettings: UserSettings
    

    在您的视图中,您可以访问它,而无需传递它。

    【讨论】:

    • 非常感谢!我认为这是不可能的,因为我宣布它为“最终”!
    • @davidev 我没有注意到它是同一个环境,你的编辑实际上应该在最上面;)
    • @pawello2222 是的.. 它在 SwiftUI 中运行得非常好。谢谢,不过你还是早点做了正确的答案。我太慢了:P
    【解决方案2】:

    如果您调用UserSettings(),它将为您的类创建一个新实例

    您需要传递正确的UserSettings 实例(而不是创建一个新实例):

    MainView.swift

    @main
    struct TestApp: App {
        @StateObject var userSettings = UserSettings()
        
        var body: some Scene {
            WindowGroup {
                ContentView()
                    .environmentObject(userSettings) // pass here
            }
        }
    }
    

    ContentView.swift

    MainView()
        .environmentObject(userSettings) // pass here
        .tabItem { Image(systemName: "location") }
        .tag(0)
    NavigationView {
        SettingsView()
            .environmentObject(userSettings) // pass here
            .navigationTitle("Settings")
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-06
    • 2022-08-03
    • 2018-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多