'Using @EnvironmentObject properly

I am just trying to get my updated value to display in my application after it receives a new value from bluetooth core. I know the value in the class is updating properly because I can see it in my print statement. My problem is that my @EnvironmentObject itself is not updating in the view so its always showing "No Value Yet"

Any help would be appreciated I am new to IOS!

import SwiftUI
import CoreBluetooth
import UIKit

let weightScaleCBUUID = CBUUID(string: "0x181D")
let massPoundCharacteristicCBUUID = CBUUID(string: "0x27B8")


class HRMViewController: UIViewController, ObservableObject  {
    
    @IBOutlet weak var bodySensorLocationLabel: UILabel!
    var centralManager: CBCentralManager!
    var weightPeripheral: CBPeripheral!
    @Published var willWork: String = "No Value Yet"
    override func viewDidLoad() {
        super.viewDidLoad()
        
        centralManager = CBCentralManager(delegate: self, queue: nil)
        // Make the digits monospaces to avoid shifting when the numbers change
    }
    
}

extension HRMViewController: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .unknown:
            print("central.state is .unknown")
        case .resetting:
            print("central.state is .resetting")
        case .unsupported:
            print("central.state is .unsupported")
        case .unauthorized:
            print("central.state is .unauthorized")
        case .poweredOff:
            print("central.state is .poweredOff")
        case .poweredOn:
            print("central.state is .poweredOn")
            centralManager.scanForPeripherals(withServices: [weightScaleCBUUID])
        @unknown default:
            print("Something is completely wrong here")
        }
    }
    
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,
                        advertisementData: [String: Any], rssi RSSI: NSNumber) {
        print(peripheral)
        
        // copy the peripheral instance
        weightPeripheral = peripheral
        weightPeripheral.delegate = self
        
        centralManager.stopScan()
        centralManager.connect(weightPeripheral)
        
    }
    
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        if peripheral == weightPeripheral {
            print("Connected!")
            weightPeripheral.discoverServices([weightScaleCBUUID])
        } else {
            print("Something went wrong in didConnect")
        }
        
    }
    
    
}

extension HRMViewController: CBPeripheralDelegate {
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        guard let services = peripheral.services else { return }
        for service in services {
            print(service)
            peripheral.discoverCharacteristics([massPoundCharacteristicCBUUID], for: service)
            
        }
    }
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic,
                    error: Error?) {
        switch characteristic.uuid {
        case massPoundCharacteristicCBUUID:
            if let CurrWeightValue = String(bytes: characteristic.value![1...6], encoding: .utf8) {
//                print(CurrWeightValue)
                willWork = CurrWeightValue
                print(willWork)
                //        bodySensorLocationLabel!.text = CurrWeightValue
            } else {
                print("not a valid UTF-8 sequence")
            }
            
            //      let weightValue = weightHelper(from: characteristic)
            //      // print(weightValue)
            //      peripheral.setNotifyValue(true, for: characteristic)
            //      bodySensorLocationLabel.text = weightValue
        default:
            print("Unhandled Characteristic UUID: \(characteristic.uuid)")
        }
    }
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService,
                    error: Error?) {
        guard let characteristics = service.characteristics else { return }
        
        for characteristic in characteristics {
            if characteristic.properties.contains(.notify) {
                print("\(characteristic.uuid): properties contains .notify")
                peripheral.setNotifyValue(true, for: characteristic)
            }
        }
    }
    
}

struct HRMViewControllerRepresented: UIViewControllerRepresentable {
    
    var centralManager: CBCentralManager!
    var weightPeripheral: CBPeripheral!
    weak var bodySensorLocationLabel: UILabel!
    var willWork = ""
    func makeUIViewController(context: Context) -> HRMViewController {
        return HRMViewController()
    }
    
    func updateUIViewController(_ uiViewController: HRMViewController, context: Context) {
        uiViewController.centralManager = centralManager
        uiViewController.weightPeripheral = weightPeripheral
        uiViewController.bodySensorLocationLabel = bodySensorLocationLabel
        uiViewController.willWork = willWork
        uiViewController.viewDidLoad()
    }
}


struct SessionsView: View {
    @EnvironmentObject var userController: HRMViewController
    var body: some View {
        VStack{
            Text("Howdy Number \(userController.willWork)").padding()
            HRMViewControllerRepresented()
            
        }
            
        
        
    }
}

struct SessionsView_Previews: PreviewProvider {
    static var previews: some View {
        SessionsView().environmentObject(HRMViewController())
    }
}
struct ContentView: View {
    var body: some View {
        TabView {
            HomeView()
                .tabItem() {
                    Image("home-icon")
                        .renderingMode(.template)
                    Text("Home")
                }
            SessionsView().environmentObject(HRMViewController())
                .tabItem() {
                    Image("sessions-icon")
                        .renderingMode(.template)
                    Text("Sessions")
                }
            ReportsView()
                .tabItem() {
                    Image("reports-icon")
                        .renderingMode(.template)
                    Text("Reports")
                }
            SettingsView()
                .tabItem() {
                    Image("settings-icon")
                        .renderingMode(.template)
                    Text("Settings")
                }
        }
        
        
    }
}


Solution 1:[1]

Turns out it was very simple once I started implementing this protocol: Pass variable from UIViewController to SwiftUI View

Here is my final implementation using MVVM:

    class SharedViewModel: ObservableObject {
        @Published var myString = "---"
        @Published var centralManager: CBCentralManager!
        @Published var weightPeripheral: CBPeripheral!
    }
    
    //Not an extension
    struct UIKitViewController_UI: UIViewControllerRepresentable {
        typealias UIViewControllerType = WSViewController
        var sharedVM: SharedViewModel
        
        func makeUIViewController(context: Context) -> WSViewController {
            return WSViewController(vm: sharedVM)
        }
        
        
        func updateUIViewController(_ uiViewController: WSViewController, context: Context) {
            
        }
        
    }

//My bluetooth Class
class WSViewController: UIViewController {
    let sharedVM: SharedViewModel
    var weightPeripheral: CBPeripheral!
    
    
    
    init(vm: SharedViewModel) {
        self.sharedVM = vm
        super.init(nibName: nil, bundle: nil)
        Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
            self.methodThatChangeValueOfString()
        }
    }
    ...

// then used in the view struct like this
struct SessionsView: View {
    @StateObject var sharedVM: SharedViewModel = SharedViewModel()
    @EnvironmentObject var myWeights: StoredWeights

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1