【问题标题】:SwiftUI cant bind injected valueSwiftUI 无法绑定注入的值
【发布时间】:2020-09-22 16:53:43
【问题描述】:

我发现this demo project 展示了如何在 swiftU 中使用 clean swift,所以我尝试自己做这样的事情。我在使用 Core Data 时遇到了问题。作为干净的 swift 架构,只有一个源(在我的例子中是 appState)可以将数据传递给查看。所以我创建了注入容器,它有 interactorappState。 容器:

struct DIContainer: EnvironmentKey {

    @ObservedObject var appState: AppState
    let interactors: Interactors

    init(appState: AppState, interactors: Interactors) {
        self.appState = appState
        self.interactors = interactors
    }
class AppState: ObservableObject, Equatable {
    var userData = UserData()
}

extension AppState {
    class UserData: ObservableObject, Equatable {
        @Published var places:[Place] = []
}

我注入这样的环境:

@Environment(\.injected) private var injected: DIContainer

最后是使用它的视图:

var body: some View {
        NavigationView {
            ZStack {
                List {
                    ForEach(injected.$appState.userData.places.wrappedValue){ place in
                        PlaceRow(place: place)
                    }
....

问题是即使加载了数组,视图也不会对此做出反应。只有当我导航到其他视图时它才会刷新。此外,当我向数组中删除或添加新元素时,视图没有任何变化。 如果您能给我一些想法,那就太好了。 我用 google 搜索了 4 天,我发现的一切都不适合我。

【问题讨论】:

    标签: ios swift binding swiftui


    【解决方案1】:

    如果您像这样将DIContainer 注入您的View

    @Environment(\.injected) private var injected: DIContainer
    

    请记住,当DIContainer 属性发生更改时,您的View 不会刷新。您必须手动观察它们。

    您可以尝试以下解决方案之一:

    1) 订阅AppState 属性对.onReceive 的更改:

    @Environment(\.injected) private var injected: DIContainer
    
    var body: some View {
        NavigationView { ... }
            .onReceive(injected.appState.userData.$places) { places in
                // do something with places, 
                // eg. assign to a @State variable to be used in a `ForEach` loop...
            }
    }
    

    2)UserData 直接注入为@EnvironmentObject

    @EnvironmentObject var userData: UserData
    
    ContentView().environmentObject(container.appState.userData)
    

    由于UserData 是一个ObservableObject,它会在任何@Published 属性(例如places)被修改时发生变化。

    3) 订阅ViewModel 中的AppState/UserData 并观察View 中唯一的ViewModel

    更详细的解释可以在您在问题中链接的同一演示项目的this 版本中找到。

    【讨论】:

    • 感谢您的回答。第一个解决方案部分有效,但问题是,当我更新数组中的某个对象时,除非我向数组中添加新项目,否则视图不会改变。
    • 是的,那是因为您观察到places 而不是它的项目。如果您更改项目,places 变量将保持不变。这与我上面解释的DIContainer 的问题相同。
    • 我真的无法理解。我完全按照您在上面的第一个解决方案中显示的方式进行了操作。我还在 userData 类中添加了self.objectWillChange.send() 到我的placeswillSet。我应该怎么做才能观察places而不是它的项目??
    • 解决方案之一是将Place 设为struct 而不是class。你可以在这个问题的答案中找到更详细的解释:Why an ObservedObject array is not updated in my SwiftUI application?
    猜你喜欢
    • 2021-10-28
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 2014-08-27
    • 1970-01-01
    相关资源
    最近更新 更多