I am working on a SwiftUI program to control an external device. In this case, the device is an amateur radio transceiver (to be specific, an Icom IC-7610). The device can be controlled over ethernet using UDP datagrams. I have the basic UDP communication working. My question is how best to use SwiftUI or Combine (or is there another alternative?) to transfer information from the user to the transceiver and vice versa.
The IC-7160 has dozens of parameters that can be set and/or queried. The computer (Mac) can request the transciever to return the value of parameter or instruct the transceiver to set a parameter to a particular value.
I'm working on the part of my program that displays the transciever's parameters on the Mac screen. I have a (model) class that manages the UDP interface. This class has a single PassthroughSubject publisher. The type of the publisher is an enum that has (or will have when I'm finished) cases with associated values for each parameter (parameters may be of different types: Int's, Float's, String's or enum's). When the model processes a UDP datagram from the transciever that has a parameter value, it sends an enum instance to the publisher.
My ViewModel class subscribes to this publisher. The subscriber method receives the enum on the main thread. It has a switch statement that updates separate @Published values, one for each parameter. The views then use these @Published values to update the display when the transceiver parameters change.
Here are my questions:
It seems like with the PassthroughSubject and the @Published values, it seems like the program is chaining two subscriptions. Is there a way that the views can subscribe directly to changes in the model? If so, should they?
Does it make sense to use the enum to route all the changes through a single PassthroughSubject or should I have one PassthroughSubject for each of the parameters (again there will be dozens)? That would mean that there would be dozens of subscriber methods in the ViewModel.
In a previous iteration of the design (before I saw a video on the Combine framework), when my ViewModel instantiated the Model class, it passed a callback closure to the Model class. The model class used the callback instead of a publisher, but still passed an instance of the enum. How does a callback closure compare to a publisher?
Lastly (for now), should the interface from the view to the ViewModel be an @ObservedObject or an @StateObject? The source of truth is actually the parameters as stored in the transceiver.
If you'd like to see my work as it progresses, I have published a copy of my local XCode repository at https://github.com/microenh/NetworkIcom
Thanks,
Mark