我想用从LocationManager传入的数据更新ChallengeManager类的Published属性。以下是带有相关位的简化代码:
LocationManager
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)
...
ChallengeManager
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()
...
(老实说,我可以通过在视图中为LocationManager添加一个ObservedObject,然后将值传递到那里的函数中来获得我想要的结果。但我不喜欢对多个视图这样做。我还希望loadChallenge((能做更多繁重的工作。在我看来,它应该是真理的唯一来源。否?(
问题:
如果我试图访问ContentView中的challengeManager.challengeToDisplay,则该值始终为零。loadChallenge((函数中的打印语句告诉我来自locationManager的值被正确接收。但是@Published var challengeToDisplay并没有改变。有人能告诉我我做错了什么吗
谢谢!
LocationManager
中的challengeManager
和ContentView
中的challengeManager
是两个不同的实例。他们没有亲属关系。您必须使用相同的实例。
惯例是
-
@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
上的状态。
@ObservedObject var challengeManager = ChallengeManager()
这将创建ChallengeManager
的一个新实例,它将不是您在LocationManager
内部处理的实例。
在实例化ContentView
时,应该传入质询管理器,而不是为属性指定默认值。