Home > Net >  SwiftUI: Model Objects That Are Not Developer-Defined?
SwiftUI: Model Objects That Are Not Developer-Defined?

Time:12-05

Every SwiftUI tutorial/example uses model objects that are defined by ME, the guy writing the app. However, what is the best practice when the model objects are not under my direct control? For example, the HomeKit framework has an API to get all the rooms in a given home. It returns an array of HMRoom objects:

open class HMRoom: NSObject 
{
    open var name: String { get }
    open var accessories: [HMAccessory] { get }
    open var uniqueIdentifier: UUID { get }

    // Update the room's name in a HomeKit-compliant way that notifies all other HomeKit apps
    open func updateName(_ name: String) async throws
}

When I receive an array of HMRoom objects from the HomeKit API, what should I do with them to power SwiftUI? Should I create my OWN class that looks like this:

final class Room: ObservableObject
{
    @Published var name: String
    @Published var accessories: [Accessory]
    @Published var uniqueIdentifier: UUID

    private var representedRoom: HMRoom

    init(homekitRoom: HMRoom)
    {
        // Copy properties from 'homekitRoom' to self, then set `representedRoom` to `homekitRoom` so we can use it to call the updateName(:) function
    }
}

Is there, instead, a way for me to extend the HMRoom class directly to inform SwiftUI that name, accessories, and uniqueIdentifier are the properties we must watch for changes in order to reload views appropriately?

It's unclear to me what the best approach is to integrate @Published/@ObservableObject when I don't write the model classes/structs myself. Thanks.

CodePudding user response:

I have done a little reading and I think that using @Published is misleading in this case.

The main reason why is because @Published is for when there is a 2-way connection. The HRRoom does not "talk back" to HomeKit via its variables.

A private (set) might even do well here so the UI doesn't attempt to change the HMRoom directly and is forced to use the method.

Also, the HMAccessoryDelegate has many update functions that tell the app that there are changes.

Calling objectWillChange.send() after action (adding, removing, replacing) has been taken on the notice from the delegate would update the UI as required.

CodePudding user response:

Why not a class to hold all of your rooms with a published variable like this:

class Rooms: ObservableObject {

    @Published rooms: [HMRoom]

}

Isn't that your view model? You don't need the room parameters to be published; you need to know when anything changes and evaluate it from there.

  • Related