问题描述
我想用从 LocationManager 传入的数据更新我的 ChallengeManager 类的 Published 属性。 这是带有相关位的简化代码:
位置管理器
final class LocationManager: NSObject,ObservableObject {
var challengeManager = ChallengeManager()
...
//a func called from locationManager delegate converts the region to an instance of an Area object then calls a method on the ChallengeManager class like this:
challengeManager.loadChallenge(for: activeArea)
...
挑战管理器
final class ChallengeManager: ObservableObject {
@Published var isShowingChallenge = false
@Published var challengetodisplay: Challenge?
func loadChallenge(for area: Area) {
if let challenge = area.challenge { //gets challenge property of area object
self.challengetodisplay = challenge
self.isShowingChallenge = true
}
}
最后是 ContentView:
struct ContentView: View {
@Observedobject var challengeManager = ChallengeManager()
...
(老实说,我可以通过在 View 中为 LocationManager 添加一个 Observedobject 然后将值传递到那里的 func 来获得我想要的结果。但我不喜欢这样做的想法多个视图。而且我还希望 loadChallenge() 做更多繁重的工作。在我看来,它应该是唯一的事实来源。不是吗?)
问题:
如果我尝试访问 ContentView 内的challengeManager.challengetodisplay,该值始终为零。
loadChallenge() 函数中的打印语句告诉我来自 locationManager 的值被正确接收。但是@Published var challengetodisplay 没有改变。
有人可以告诉我我做错了什么吗?
谢谢!
解决方法
@ObservedObject var challengeManager = ChallengeManager()
这将创建一个新的 ChallengeManager
实例,它不会是您在 LocationManager
中处理的那个实例。
您应该在实例化 ContentView
时传入挑战管理器,而不是给属性一个默认值。
challengeManager
中的 LocationManager
和 challengeManager
中的 ContentView
是两个不同的实例。他们没有关系。您必须使用相同的实例。
约定是
-
@StateObject
创建一个对象并拥有它@StateObject var challengeManager = ChallengeManager()
-
@ObservedObject
不创建和拥有对象,它将通过视图层次结构传递。@ObservedObject var challengeManager : ChallengeManager
您也可以在视图层次结构的开头使用 @EnvironmentObject
。
附注:
SwiftUI
比 Swift 更依赖于非可选项。对于已发布的挑战,如果更像 SwiftUI,则此枚举具有关联类型
enum ChallengeState {
case idle,display(Challenge)
}
和
final class ChallengeManager: ObservableObject {
@Published var challengeState : ChallengeState = .idle
func loadChallenge(for area: Area) {
if let challenge = area.challenge { //gets challenge property of area object
challengeState = .display(challenge)
} else {
challengeState = .idle
}
}
在视图 switch
上的状态。