将EnvironmentObject传递给ObservableObject类

时间:2020-04-20 12:15:17

标签: ios swift swiftui

我制作了一个SwiftUI应用程序,该应用程序反复获取遥测数据以更新自定义视图。视图使用存储在EnvironmentObject中的变量。

struct updateEO{
    @EnvironmentObject var settings:UserSettings
    func pushSettingUpdate(telemetry: TelemetryData) {
        settings.info = telemetry
        print(settings.info)
    }
}

class DownloadTimer : ObservableObject {
    var timer : Timer!
    let didChange = PassthroughSubject<DownloadTimer,Never>()
    @Published var telemetry = TelemetryData()
    func start() {
        connectToClient()
        self.timer?.invalidate()
        self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) {
            _ in
            guard let url = URL(string: "http://127.0.0.1:25555/api/telemetry") else {
                print("Invalid URL")
                return
            }

            let request = URLRequest(url: url)

            URLSession.shared.dataTask(with: request) { data, response, error in
                if let data = data {
                    if let decodedResponse = try? JSONDecoder().decode(TelemetryData.self, from: data) {
                        DispatchQueue.main.async {
                            updateEO().pushSettingUpdate(telemetry: decodedResponse)
                        }
                        return
                    }
                }
            }.resume()
        }
    }
}

在运行时,当遥测传递到pushSettingUpdate(telemetry: decodedResponse)时,应用程序崩溃,并显示错误消息“致命错误:未找到UserSettings类型的ObservableObject”。 我知道我可能需要通过该结构的EnvironmentObject,但是我不确定如何做到这一点。任何帮助将非常感激。谢谢! :)

1 个答案:

答案 0 :(得分:2)

您应该在视图中使用@EnvironmentObject,并在需要时将其传递给模型。

在这里,struct updateEO不是视图。

我创建了一个更简单的示例,向您展示如何执行此操作:

UserSettings

class UserSettings: ObservableObject {
    @Published var info: String = ""
}

DownloadTimer

class DownloadTimer: ObservableObject {
    var timer : Timer?

    func start(settings: UserSettings) {
        self.timer?.invalidate()
        self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { t in
            settings.info = t.fireDate.description
        }
    }
}


start出现时,您调用UserSettings(以Text作为参数)。

MyView

struct MyView: View {
    private let downloadTimer = DownloadTimer()
    @EnvironmentObject var settings: UserSettings

    var body: some View {
        Text(settings.info)
            .onAppear {
                self.downloadTimer.start(settings: self.settings)
        }
    }
}

别忘了调用.environmentObject函数将UserSettings注入SceneDelegate中。

SceneDelegate

let contentView = MyView().environmentObject(UserSettings())

随着时间的流逝,您应该会看到文本更新。