1

The following code works and assigns the topLeftGameState to a timer. If the globalGameState changes to running, the topLeftGameState changes accordingly.

@Published var topLeftGameState: GameState = .notReady
@Published var topRightGameState: GameState = .notReady
@Published var bottomLeftGameState: GameState = .notReady

private let timerPublisher = Timer.publish(every: 0.01, on: .main, in: .common)    
// ...
 timerPublisher.autoconnect().sink(receiveValue: { currentDate in
        switch self.globalGameState {
        case .running(startDate: let startDate):
            let elapsedTime = currentDate - startDate
            if self.topLeftGameState == .ready { //,   {
                self.topLeftGameState = .running(elapsedTime: elapsedTime.timeInterval)
            }
            if case .running(elapsedTime: _) = self.topLeftGameState {
                self.topLeftGameState = .running(elapsedTime: elapsedTime.timeInterval)
            }
            
            if self.topRightGameState == .ready { //,   {
                self.topRightGameState = .running(elapsedTime: elapsedTime.timeInterval)
            }
            if case .running(elapsedTime: _) = self.topRightGameState {
                self.topRightGameState = .running(elapsedTime: elapsedTime.timeInterval)
            }
            
            if self.bottomLeftGameState == .ready { //,   {
                self.bottomLeftGameState = .running(elapsedTime: elapsedTime.timeInterval)
            }
            if case .running(elapsedTime: _) = self.bottomLeftGameState {
                self.bottomLeftGameState = .running(elapsedTime: elapsedTime.timeInterval)
            }
        default: ()
        }
    }).store(in: &cancellables)

So this code looks really ugly and I would like to write a function for all the @Published variables:

    addTimePublisher(for: topLeftGameState)
    addTimePublisher(for: topRightGameState)
        //...
    private func addTimePublisher(for gameState: Published<GameState>.Publisher) {
        timerPublisher.autoconnect().sink(receiveValue: { currentDate in
            switch self.globalGameState {
            case .running(startDate: let startDate):
                let elapsedTime = currentDate - startDate
                if self.gameState == .ready {
                    self.gameState = .running(elapsedTime: elapsedTime.timeInterval)
                }
                if case .running(elapsedTime: _) = self.gameState {
                    self.gameState = .running(elapsedTime: elapsedTime.timeInterval)
                }
                
            default: ()
            }
            print(currentDate)
        }).store(in: &cancellables)
    }

This throw an error: Cannot infer contextual base in reference to member 'ready'

I do not know how to get the appropriate value from the publisher? Does anyone have any advice for me?

Edit: How can I write a function and pass @Published variables?

kuzdu
  • 7,124
  • 1
  • 51
  • 69
  • It would make more sense to inject the entire viewModel with the published property as an EnvironmentObject rather than trying to pass in individual `@Published` properties. – Andy Ibanez Oct 28 '20 at 18:52
  • Unclear to me what you're doing. What does "connected to the `timerPublisher`" mean? How and where are you attempting to call `addTimePublisher` and where is all of this happening - in the same view model? You might be asking an X-Y question. But to answer your last question - to get the value from a publisher you need to subscribe to (with `.sink`, just like you did with the timer publisher). I'm guessing that's not what you actually need – New Dev Oct 28 '20 at 20:38
  • I'm sorry, I updated my question. – kuzdu Oct 29 '20 at 05:00

0 Answers0