简体   繁体   English

为什么 SwiftUI 不在这里更新视图?

[英]Why does SwiftUI not update a view here?

The background color and text in ReadyDashboardView below don't update when isConnected is updated.当 isConnected 更新时,下方 ReadyDashboardView 中的背景颜色和文本不会更新。 Obviously I want to update the view when the connection is made.显然,我想在建立连接时更新视图。 I was expecting that publishing everything in the chain to that variable would make it update instantly in swiftui.我期待将链中的所有内容发布到该变量会使其在 swiftui 中立即更新。 Instead, it's always rendering using the value provided when the variable is instantiated.相反,它总是使用实例化变量时提供的值进行渲染。 Here's a very simplified look at the situation:这是一个非常简化的情况:

Is there another swiftui feature i should be using or am I going to have to make some sweeping changes to my codebase?我应该使用另一个 swiftui 功能还是我必须对我的代码库进行一些彻底的更改?

import SwiftUI

@main
struct TestApp: App {
    @StateObject private var env = PrinterEnv()
    
    var body: some Scene {
        WindowGroup {
            ReadyDashboardView()
                .environmentObject(env)
        }
    }
}

struct ReadyDashboardView: View {
    @EnvironmentObject var env: PrinterEnv

    var body: some View {
        VStack {
            HStack {
                Spacer()
                VStack {
                    Text(env.selectedPrinter?.isConnected ?? false ? "Printer Ready" : "Not Connected")
                        .padding(.bottom)
                }
                Spacer()
            }
            .background(env.selectedPrinter?.isConnected ?? false ? .green : .red)
           
        Button("Connect") { env.selectedPrinter?.isConnected = true }
        Button("Disconnect") { env.selectedPrinter?.isConnected = false }
            
        }
    }
}

class PrinterEnv: ObservableObject {
    @Published var configuredPrinters: [Printer] = []
    @Published var selectedPrinter: Printer?
    
    init() {
        configuredPrinters.append(contentsOf: [Printer()])
        selectedPrinter = configuredPrinters.first
    }
}

class Printer: ObservableObject {
    @Published var isConnected = false
}

I suggest you do not nest ObservableObject , it does not work very well.我建议你不要嵌套ObservableObject ,它不能很好地工作。

Try a Printer struct for example, such as:例如,尝试使用Printer结构,例如:

struct Printer: Identifiable {
    let id = UUID()
    var isConnected = false
}

I do not think the problem is specifically related to nested observable objects.我不认为这个问题与嵌套的可观察对象特别相关。 Nesting them is working fine and is even recommended by community members as the best way to manage app wide states and ensure performance is acceptable.嵌套它们运行良好,甚至被社区成员推荐为管理应用程序范围状态并确保性能可接受的最佳方式。

See this: https://www.fivestars.blog/articles/app-state/看到这个: https://www.fivestars.blog/articles/app-state/

That said, I believe it's probably related to the wrapping of the observable object with @Published property wrapper.也就是说,我相信它可能与使用@Published属性包装器包装可观察的 object 有关。

Try this in a playground:在操场上试试这个:

import SwiftUI

class AppState: ObservableObject {
    let fooState = FooState()
    let barState = BarState()
}

class FooState: ObservableObject {
    @Published var foo: Int = 42
}

class BarState: ObservableObject {
    @Published var bar: String = Date().debugDescription
}

struct FooView: View {

    @EnvironmentObject var fooState: FooState

    var body: some View {
        Text("foo: \(fooState.foo)")
    }
}

struct BarView: View {

    @EnvironmentObject var barState: BarState

    var body: some View {
        Text("bar: \(barState.bar)")
    }
}

struct ContentView: View {

    @EnvironmentObject var appState: AppState

    var body: some View {
        VStack {
            Spacer()

            FooView()
                .environmentObject(appState.fooState)

            Button("update foo") {
                appState.fooState.foo = Int.random(in: 1...100)
            }

            Spacer()

            BarView()
                .environmentObject(appState.barState)

            Button("update bar") {
                appState.barState.bar = Date().debugDescription
            }

            Spacer()
        }
    }
}

import PlaygroundSupport

PlaygroundPage.current.liveView = UIHostingController(
    rootView: ContentView()
        .frame(width: 320, height: 414)
        .environmentObject(AppState())
)

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM