SwiftUI:如何用位置管理器类的已发布属性更新一个类(ObservableObject)的已发布特性



我想用从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中的challengeManagerContentView中的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时,应该传入质询管理器,而不是为属性指定默认值。

相关内容

  • 没有找到相关文章

最新更新