Search code examples
iosswiftswiftuiwatchoswatchconnectivity

Why is the published variable's updated value not getting reflected when used in function?


I'm trying to follow this tutorial to use WatchConnectivity with SwiftUI. In the view model for the watch, I'm able to successfully receive the message being sent from the iPhone and set it in the published variable of the class but when I try to use that value in the ContentView, I only see the initial value and not the updated value.

ViewModelWatch

import Foundation
import WatchConnectivity

class ViewModelWatch : NSObject,  WCSessionDelegate, ObservableObject{
    var session: WCSession
    @Published var sessionId = ""
    
    init(session: WCSession = .default){
        self.session = session
        super.init()
        self.session.delegate = self
        session.activate()
    }
    
    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        
    }
    
    func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
            DispatchQueue.main.async {
                if let sessionId = message["sessionId"] {
                    self.sessionId = sessionId as! String
                }
            }
        }
}

ContentView

import SwiftUI

struct ContentView: View {
    @ObservedObject var model = ViewModelWatch()
    
    var body: some View {
        Button(action: startAction, label: {
          Text("Test")
        })
      
       
    }
    
    func startAction() {
        print("sessionId", self.model.sessionId)

    }
}

Solution

  • @Asperi - How would you recommend getting the updated sessionId value then?

    A solution would be to move action into model, so it operates with own property, and use that action directly in button (or button action closure), like

    class ViewModelWatch : NSObject,  WCSessionDelegate, ObservableObject{
    
        // ... other code
    
        func startAction() {                     // << move here
            print("sessionId", self.sessionId)
    
        }
    }
    
    struct ContentView: View {
        @ObservedObject var model = ViewModelWatch()
    
        var body: some View {
            Button(action: model.startAction, label: {     // << use model
              Text("Test")
            })
        }
    }