Adding New Homes and Rooms to HomeKit within a SwiftUI app

Adding New Homes and Rooms to HomeKit within a SwiftUI app

Understand how to add or remove Homes and Rooms to the HomeKit environment within a SwiftUI app.

Even though it is most convenient to manage the general configuration of your HomeKit setup through the native Home app on iOS, iPadOS, or macOS, you might also want to add some general capabilities to your HomeKit-enabled app.

For example, beyond interacting with smart home Accessories, you may also want to add additional Rooms or even Homes to your HomeKit environment. This article shows how to list any Home and its Rooms and how to add additional Rooms or Homes to the configuration. When adding accessories through the default HomeKit workflow, they can then be assigned to a Home and Room.

To develop a HomeKit-enabled app you need to add the HomeKit capability to your Xcode project. This can be done in the Project Settings and the Signing & Capabilities pane of your target. Also, you have to add an entitlement to your projects info.plist to ask the user for permission to access HomeKit. In your project settings Info pane, you can add a new entry for the Custom iOS Target Properties. Provide a meaningful description of why you need access to HomeKit for the NSHomeKitUsageDescription key. To learn more about these requirements, follow our tutorial "Creating a HomeKit-enabled App with SwiftUI".

⚠️
Without the usage description, your app will crash when you first try to use HomeKit, so make sure you don't forget it. 

Let's explore how to display any number of Homes available in HomeKit and any Rooms configured inside. Then, let's also understand how we can add and also remove additional Homes and Rooms to the HomeKit environment.

Finding Available Homes

In this example, we will use a HomeStore class to manage access to HomeKit and reference it from the SwiftUI views throughout the app as a reference type. It uses a private instance of HMHomeManager, which serves as the primary manager for any number of Homes of a user. To monitor changes made to any Home, we adopt the HMHomeManagerDelegate Protocol to track the state of the home network.

The HomeStore also comes with a @Published array of HMHome, which is the primary unit of living space inside HomeKit, that can be composed of Rooms organized in Zones. With this simple setup, we can start exploring the HomeKit configuration for available Homes.

import Foundation
import HomeKit
import Combine

class HomeStore: NSObject, ObservableObject, HMHomeManagerDelegate {
    
    
    @Published var homes: [HMHome] = []
    private var manager: HMHomeManager!

    override init(){
        super.init()
        load()
    }
    
    func load() {
        if manager == nil {
            manager = .init()
            manager.delegate = self
        }
    }
    

    func homeManagerDidUpdateHomes(_ manager: HMHomeManager) {
        print("DEBUG: Updated Homes!")
        self.homes = self.manager.homes
    }
}

In a HomeView SwiftUI view you can then display a List of Homes like this:

import SwiftUI
import HomeKit

struct HomeView: View {
    
    @ObservedObject var model: HomeStore
    
    var body: some View {
        List {
            Section(header: HStack {
                Text("My Homes")
            }) {
                ForEach(model.homes, id: \.uniqueIdentifier) { home in
                        Text("\(home.name)")
                }
            }
        }
    }
}

Adding and Removing Homes

Now, if you wanted to add an additional Home to the configuration, you can extend the HomeStore with a simple function addHome(). In this example we give it a randomized name with a UUID, in a real app this could be provided by the user. To delete a home, a similarly simple function removeHome(home: HMHome) can be added that takes a HMHome as a parameter.

class HomeStore: NSObject, ObservableObject, HMHomeManagerDelegate {
    
    [...]
    
    func addHome() {
        manager.addHome(withName: "NewHome \(UUID())") { [weak self] (home, error) in
            guard let self = self else {return}
            self.homeManagerDidUpdateHomes(self.manager)

        }
    }
    
    func removeHome(home: HMHome) {
        manager.removeHome(home) { [weak self] error in
            guard let self = self else {return}
            self.homeManagerDidUpdateHomes(self.manager)
        }
    }
}

Then, within our SwiftUI view, we could add a simple Button that calls an addhome() function that accesses the newly created function in the HomeStore to add a new Home to the List.

struct HomeView: View {
    
    @State private var path = NavigationPath()
    @ObservedObject var model: HomeStore
    
    var body: some View {
        NavigationStack(path: $path) {
            List {
                Section(header: HStack {
                    Text("My Homes")
                }) {
                    ForEach(model.homes, id: \.uniqueIdentifier) { home in
                        NavigationLink(value: home){
                            Text("\(home.name)")
                        }.navigationDestination(for: HMHome.self){
                            RoomsView(homeId: $0.uniqueIdentifier, model: model)
                        }
                    }
                }
                Button("Add another Home"){
                    addHome()
                }
            }
        }
    }
    
    func addHome(){
        model.addHome()
    }
    
}

While we are at it, let's add a detail view for the List, so we can display a Button to remove the Home from HomeKit. The RoomView could look like this:

struct RoomsView: View {
    
    var homeId: UUID
    @ObservedObject var model: HomeStore
    
    var body: some View {
    	Button("Remove this Home"){
        	removeHome()
    	}
	}
    
	func removeHome(){
        guard let thisHome = model.homes.first(where: {$0.uniqueIdentifier == homeId}) else {
            print("ERROR: No Home was found!")
            return
        }
        model.removeHome(home: thisHome)
    }
}

Now that we established how to work with Homes, let's explore how we can find, add and remove Rooms in HomeKit.

Become a free member or log in to proceed.