0

I want to update the Published property of my ChallengeManager class with data passed in from LocationManager. Here is the simplified code with the relevant bits:

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
   }
}

Finally, the ContentView:

struct ContentView: View {
   @ObservedObject var challengeManager = ChallengeManager()
...

(To be honest, I can get the results I want by adding an ObservedObject for the LocationManager in the View and then passing the values into a func there. But I don't like the idea of doing this for multiple views. And I also want loadChallenge() to do more heavy lifting. It seems to me that it should be the single source of truth. No?)

The problem:

If I try to access challengeManager.challengeToDisplay inside the ContentView, the value is always nil. Print statements in the loadChallenge() func tell me that the value from the locationManager is being received correctly. But @Published var challengeToDisplay is not changing. Can someone please tell me what I am doing wrong?
Thanks!

4

2 回答 2

0
@ObservedObject var challengeManager = ChallengeManager()

这是创建一个新的实例ChallengeManager,它不会是你在里面处理的那个LocationManager

您应该在实例化时传入挑战管理器ContentView,而不是为属性提供默认值。

于 2021-05-27T13:27:03.700 回答
0

challengeManagerinLocationManagerchallengeManagerinContentView是两个不同的例子。它们不相关。您必须使用相同的实例。

公约是

  • @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状态。

于 2021-05-27T13:27:43.270 回答