SwiftUI - 父视图中的 StateObject 在子视图模型中不可用

问题描述 投票:0回答:1
// In my root view aka Parent View
import SwiftUI

struct RootView: View {
    @StateObject private var devices = DevicesViewModel()
    
    var body: some View {
        ScrollView {
            UnitStatusCard(devicesVM: devices)
        }
        .onAppear() {
            devices.fetchDevices()
        }
    }
}

// DeviceViewModel.swift - Parent View Model
import Foundation

class DevicesViewModel: ObservableObject {
    @Published var models: [Device] = []
    
    private let networkManager = NetworkManager<[Device]>()
    
    init() {
        fetchDevices()
    }
    
    public func fetchDevices() {
        Task {
            do {
                if let unitId = UserDefaults.standard.string(forKey: kUnit) {
                    let models = try await networkManager.fetchData(path: "/api/test")

                    DispatchQueue.main.async {
                        self.models = models
                    }
                }
            } catch {...}
        }
    }
}

// UnitStatusCard.swift - Child View
struct UnitStatusCard: View {
     @StateObject var unitStatusCardVM: UnitStatusCardViewModel
    
    init(devicesVM: DevicesViewModel) {
        self._unitStatusCardVM = StateObject(wrappedValue: UnitStatusCardViewModel(devicesVM: devicesVM))
    }
    
    var body: some View {
        StatusView()
            .onAppear() {
                unitStatusCardVM.getStatusMeta()
            }
    }
}

// UnitStatusCardViewModel.swift - Child View Model
class UnitStatusCardViewModel: ObservableObject {
     @Published var value: String = "Good"
    
     var devicesVM: DevicesViewModel
    
    init(devicesVM: DevicesViewModel) {
        self.devicesVM = devicesVM
    }
    
    public func getStatusMeta() {
        print(devicesVM.models) // value is [], WHY??
    }
}

DeviceViewModel.swift
中,有Api调用,成功获取结果,没有错误。 然而,当我将结果传递给我的子视图模型(
UnitStatusCardViewModel
)时,即使根据 ProxyMan 正确获取了该值,该值也是空的。

    public func getStatusMeta() {
        print(devicesVM.models) // value is [], WHY??
    }

这是为什么以及如何解决?

ios swift swiftui mobile
1个回答
0
投票

我认为有几个因素可能导致这个结果。

fetchDevices
方法正在内部执行异步操作(虽然没有标记为异步,但它执行任务并且似乎执行某种网络调用。根据您检查模型的时间,在获取之前打印值(例如
getStatusMeta
onAppear
上被调用,可能是在获取完成其内部执行之前。

我建议不要在 init 方法中运行

fetchDevices
,它无论如何都会在 RootView 的 onAppear 中调用,这意味着它会被调用两次,而且最终的操作会导致在创建对象时发生 ui 更改在附加到 Swift UI 视图之前或同时,可能会导致 ui 线程方面出现不良结果(那些臭名昭著的紫色/紫色警告可能会出现在 Xcode 中)开发期间)

还有一件事:为了遵守严格的并发检查,强烈建议不要像您那样使用老式的 DispatchAsync

DispatchQueue.main.async {
    self.models = models
}

而是改变它

await MainActor.run {
    self.models = … // make sure Device is Sendable or marked as @unchecked Sendable
}

甚至标记 作为 @MainActor 的视图模型可能是一种替代方案,因此 DeviceViewModel 属性上的任何更改都将被隔离并在主线程上本质上执行

© www.soinside.com 2019 - 2024. All rights reserved.