
Homekit
- 2.1k installs
- 944 repo stars
- Updated July 15, 2026
- dpearson2699/swift-ios-skills
homekit is an agent skill that Control smart-home accessories and commission Matter devices using HomeKit and MatterSupport. Use when managing homes/rooms/accessories, creating action sets or triggers,.
About
The homekit skill. Control smart-home accessories and commission Matter devices using HomeKit and MatterSupport. Use when managing homes/rooms/accessories, creating action sets or triggers, reading accessory characteristics, onboarding Matter devices, or building a third-party smart-home ecosystem app. HomeKit manages the home/room/accessory model, action sets, and triggers. MatterSupport handles device commissioning into your ecosystem. Enable the **HomeKit** capability in Xcode (Signing & Capabilities) 2. Add to Info.plist: ### MatterSupport Configuration For Matter commissioning into your own ecosystem: 1. Add a **MatterSupport Extension** target and set its principal class to a subclass 2. Add only if the caller supplies a Matter setup payload programmatically ### Availability Check ## HomeKit Data Model HomeKit organizes home automation in a hierarchy: ### Initializing the Home Manager Create a single and implement the delegate to know when data is loaded.
- [HomeKit Data Model](#homekit-data-model)
- [Managing Accessories](#managing-accessories)
- [Reading and Writing Characteristics](#reading-and-writing-characteristics)
- [Action Sets and Triggers](#action-sets-and-triggers)
- [Matter Commissioning](#matter-commissioning)
Homekit by the numbers
- 2,058 all-time installs (skills.sh)
- +106 installs in the week ending Jul 29, 2026 (Skillselion tracking)
- Ranked #108 of 1,039 Mobile Development skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 31, 2026 (Skillselion catalog sync)
homekit capabilities & compatibility
- Capabilities
- [homekit data model](#homekit data model) · [managing accessories](#managing accessories) · [reading and writing characteristics](#reading a · [action sets and triggers](#action sets and trig · [matter commissioning](#matter commissioning)
- Use cases
- testing · debugging · ci cd
What homekit says it does
HomeKit manages the home/room/accessory model, action sets, and triggers.
MatterSupport handles device commissioning into your ecosystem.
npx skills add https://github.com/dpearson2699/swift-ios-skills --skill homekitAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2.1k |
|---|---|
| repo stars | ★ 944 |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 15, 2026 |
| Repository | dpearson2699/swift-ios-skills ↗ |
How do I apply homekit correctly using the SKILL.md workflows and reference files?
Control smart-home accessories and commission Matter devices using HomeKit and MatterSupport. Use when managing homes/rooms/accessories, creating action sets or triggers, reading accessory characteris
Who is it for?
Developers and software engineers working with homekit patterns from the skill documentation.
Skip if: Skip when cached docs are empty, boilerplate-only, or outside the skill documented scope.
When should I use this skill?
Control smart-home accessories and commission Matter devices using HomeKit and MatterSupport. Use when managing homes/rooms/accessories, creating action sets or triggers, reading accessory characteristics, onboarding Mat
What you get
Grounded homekit guidance with highlights, triggers, and evidence quotes from SKILL.md.
- HomeKit automation Swift code
- scene and trigger configuration
- capability prerequisite checklist
Files
HomeKit
Control home automation accessories and commission Matter devices. HomeKit manages the home/room/accessory model, action sets, and triggers. MatterSupport handles device commissioning into your ecosystem. Targets Swift 6.3 / iOS 26+.
Contents
- Setup
- HomeKit Data Model
- Managing Accessories
- Reading and Writing Characteristics
- Action Sets and Triggers
- Matter Commissioning
- MatterAddDeviceExtensionRequestHandler
- Common Mistakes
- Review Checklist
- References
Setup
HomeKit Configuration
1. Enable the HomeKit capability in Xcode (Signing & Capabilities) 2. Add NSHomeKitUsageDescription to Info.plist:
<key>NSHomeKitUsageDescription</key>
<string>This app controls your smart home accessories.</string>MatterSupport Configuration
For Matter commissioning into your own ecosystem:
1. Add a MatterSupport Extension target and set its principal class to a MatterAddDeviceExtensionRequestHandler subclass 2. Add NSBonjourServices entries for _matter._tcp, _matterc._udp, and _matterd._udp 3. Add com.apple.developer.matter.allow-setup-payload only if the caller supplies a Matter setup payload programmatically
Availability Check
import HomeKit
let homeManager = HMHomeManager()
// HomeKit is available on iPhone, iPad, Apple TV, Apple Watch,
// Mac Catalyst, and Vision Pro.
// Authorization is handled through the delegate:
homeManager.delegate = selfHomeKit Data Model
HomeKit organizes home automation in a hierarchy:
HMHomeManager
-> HMHome (one or more)
-> HMRoom (rooms in the home)
-> HMAccessory (devices in a room)
-> HMService (functions: light, thermostat, etc.)
-> HMCharacteristic (readable/writable values)
-> HMZone (groups of rooms)
-> HMActionSet (grouped actions)
-> HMTrigger (time or event-based triggers)Initializing the Home Manager
Create a single HMHomeManager and implement the delegate to know when data is loaded. HomeKit loads asynchronously -- do not access homes until the delegate fires.
import HomeKit
final class HomeStore: NSObject, HMHomeManagerDelegate {
let homeManager = HMHomeManager()
override init() {
super.init()
homeManager.delegate = self
}
func homeManagerDidUpdateHomes(_ manager: HMHomeManager) {
// Safe to access manager.homes now
let homes = manager.homes
let primaryHome = manager.primaryHome
print("Loaded \(homes.count) homes")
}
func homeManager(
_ manager: HMHomeManager,
didUpdate status: HMHomeManagerAuthorizationStatus
) {
if status.contains(.authorized) {
print("HomeKit access granted")
}
}
}Accessing Rooms
guard let home = homeManager.primaryHome else { return }
let rooms = home.rooms
let kitchen = rooms.first { $0.name == "Kitchen" }
// Room for accessories not assigned to a specific room
let defaultRoom = home.roomForEntireHome()Managing Accessories
Discovering and Adding Accessories
Use HomeKit and MatterSupport for home-model work: homes, rooms, HMAccessory services and characteristics, action sets, triggers and automations, HomeKit accessory setup UI, and Matter commissioning. If the same request asks about lower-level Bluetooth or Wi-Fi accessory discovery or authorization, name AccessorySetupKit as the boundary for discovery descriptors, picker authorization, ASAccessorySession events, and migration. After AccessorySetupKit setup, explicitly name both post-setup handoff targets: CoreBluetooth/GATT for Bluetooth accessories and NetworkExtension for Wi-Fi accessory network flows; neither handoff is HomeKit automation logic.
// System UI for accessory discovery
home.addAndSetupAccessories { error in
if let error {
print("Setup failed: \(error)")
}
}Listing Accessories and Services
for accessory in home.accessories {
print("\(accessory.name) in \(accessory.room?.name ?? "unassigned")")
for service in accessory.services {
print(" Service: \(service.serviceType)")
for characteristic in service.characteristics {
print(" \(characteristic.characteristicType): \(characteristic.value ?? "nil")")
}
}
}Moving an Accessory to a Room
guard let accessory = home.accessories.first,
let bedroom = home.rooms.first(where: { $0.name == "Bedroom" }) else { return }
home.assignAccessory(accessory, to: bedroom) { error in
if let error {
print("Failed to move accessory: \(error)")
}
}Reading and Writing Characteristics
Reading a Value
let characteristic: HMCharacteristic = // obtained from a service
characteristic.readValue { error in
guard error == nil else { return }
if let value = characteristic.value as? Bool {
print("Power state: \(value)")
}
}Writing a Value
// Turn on a light
characteristic.writeValue(true) { error in
if let error {
print("Write failed: \(error)")
}
}Observing Changes
Enable notifications for real-time updates:
characteristic.enableNotification(true) { error in
guard error == nil else { return }
}
// In HMAccessoryDelegate:
func accessory(
_ accessory: HMAccessory,
service: HMService,
didUpdateValueFor characteristic: HMCharacteristic
) {
print("Updated: \(characteristic.value ?? "nil")")
}Action Sets and Triggers
Creating an Action Set
An HMActionSet groups characteristic writes that execute together:
home.addActionSet(withName: "Good Night") { actionSet, error in
guard let actionSet, error == nil else { return }
// Turn off living room light
let lightChar = livingRoomLight.powerCharacteristic
let action = HMCharacteristicWriteAction(
characteristic: lightChar,
targetValue: false as NSCopying
)
actionSet.addAction(action) { error in
guard error == nil else { return }
print("Action added to Good Night scene")
}
}Executing an Action Set
home.executeActionSet(actionSet) { error in
if let error {
print("Execution failed: \(error)")
}
}Creating a Timer Trigger
var timeOfDay = DateComponents()
timeOfDay.hour = 22
timeOfDay.minute = 30
let firstFireDate = Calendar.current.nextDate(
after: Date(),
matching: timeOfDay,
matchingPolicy: .nextTime
)!
let trigger = HMTimerTrigger(
name: "Nightly",
fireDate: firstFireDate,
recurrence: DateComponents(day: 1) // Repeat every day after firstFireDate
)
home.addTrigger(trigger) { error in
guard error == nil else { return }
// Attach the action set to the trigger
trigger.addActionSet(goodNightActionSet) { error in
guard error == nil else { return }
trigger.enable(true) { error in
print("Trigger enabled: \(error == nil)")
}
}
}Creating an Event Trigger
let motionDetected = HMCharacteristicEvent(
characteristic: motionSensorCharacteristic,
triggerValue: true as NSCopying
)
let eventTrigger = HMEventTrigger(
name: "Motion Lights",
events: [motionDetected],
predicate: nil
)
home.addTrigger(eventTrigger) { error in
// Add action sets as above
}Matter Commissioning
Use MatterAddDeviceRequest to commission a Matter device into your ecosystem. This is separate from the HMHome home-automation model; it handles the Matter setup flow and calls into your MatterSupport extension.
Basic Commissioning
import MatterSupport
func addMatterDevice() async throws {
guard MatterAddDeviceRequest.isSupported else {
print("Matter not supported on this device")
return
}
let topology = MatterAddDeviceRequest.Topology(
ecosystemName: "My Smart Home",
homes: [
MatterAddDeviceRequest.Home(displayName: "Main House")
]
)
let request = MatterAddDeviceRequest(
topology: topology,
setupPayload: nil,
showing: .allDevices
)
// Presents system UI for device pairing
try await request.perform()
}When providing a setup code directly, import Matter and pass an MTRSetupPayload as setupPayload; this is the case that requires the setup-payload entitlement.
Filtering Devices
// Only show devices from a specific vendor
let criteria = MatterAddDeviceRequest.DeviceCriteria.vendorID(0x1234)
let request = MatterAddDeviceRequest(
topology: topology,
setupPayload: nil,
showing: criteria
)Combine criteria with .all([.vendorID(...), .not(.productID(...))]) or use .any(...) when any one criterion is enough.
MatterAddDeviceExtensionRequestHandler
For full ecosystem support, create a MatterSupport Extension. The extension handles commissioning callbacks. Override the needed methods, but do not call super from those overrides.
import MatterSupport
final class MatterHandler: MatterAddDeviceExtensionRequestHandler {
override func validateDeviceCredential(
_ deviceCredential:
MatterAddDeviceExtensionRequestHandler.DeviceCredential
) async throws {
// Validate the device attestation certificate
// Throw to reject the device
}
override func rooms(
in home: MatterAddDeviceRequest.Home?
) async -> [MatterAddDeviceRequest.Room] {
// Return rooms in the selected home
return [
MatterAddDeviceRequest.Room(displayName: "Living Room"),
MatterAddDeviceRequest.Room(displayName: "Kitchen")
]
}
override func configureDevice(
named name: String,
in room: MatterAddDeviceRequest.Room?
) async {
// Save the device configuration to your backend
print("Configuring \(name) in \(room?.displayName ?? "no room")")
}
override func commissionDevice(
in home: MatterAddDeviceRequest.Home?,
onboardingPayload: String,
commissioningID: UUID
) async throws {
// Use the onboarding payload to commission the device
// into your fabric using the Matter framework
}
}Common Mistakes
DON'T: Access homes before the delegate fires
// WRONG -- homes array is empty until delegate is called
let manager = HMHomeManager()
let homes = manager.homes // Always empty here
// CORRECT -- wait for delegate
func homeManagerDidUpdateHomes(_ manager: HMHomeManager) {
let homes = manager.homes // Now populated
}DON'T: Confuse HomeKit setup with Matter commissioning
// WRONG -- using HomeKit accessory setup for a Matter ecosystem app
home.addAndSetupAccessories { error in }
// CORRECT -- use MatterAddDeviceRequest for Matter ecosystem commissioning
let request = MatterAddDeviceRequest(
topology: topology,
setupPayload: nil,
showing: .allDevices
)
try await request.perform()DON'T: Forget required configuration
Matter ecosystem commissioning needs the MatterSupport extension, principal handler class, and Matter Bonjour services. Add the setup-payload entitlement only when your app provides setup codes directly.
DON'T: Create multiple HMHomeManager instances
// WRONG -- each instance loads the full database independently
class ScreenA { let manager = HMHomeManager() }
class ScreenB { let manager = HMHomeManager() }
// CORRECT -- single shared instance
@Observable
final class HomeStore {
static let shared = HomeStore()
let homeManager = HMHomeManager()
}DON'T: Write characteristics without checking metadata
// WRONG -- writing a value outside the valid range
characteristic.writeValue(500) { _ in }
// CORRECT -- check metadata first
if let metadata = characteristic.metadata,
let maxValue = metadata.maximumValue?.intValue {
let safeValue = min(brightness, maxValue)
characteristic.writeValue(safeValue) { _ in }
}Review Checklist
- [ ] HomeKit capability enabled in Xcode
- [ ]
NSHomeKitUsageDescriptionpresent in Info.plist - [ ] Single
HMHomeManagerinstance shared across the app - [ ]
HMHomeManagerDelegateimplemented; homes not accessed beforehomeManagerDidUpdateHomes - [ ]
HMHomeDelegateset on homes to receive accessory and room changes - [ ]
HMAccessoryDelegateset on accessories to receive characteristic updates - [ ] Characteristic metadata checked before writing values
- [ ] Error handling in all completion handlers
- [ ] MatterSupport extension target and principal handler configured
- [ ] Matter discovery
NSBonjourServicesentries added - [ ]
com.apple.developer.matter.allow-setup-payloadused only when providing setup codes - [ ]
MatterAddDeviceRequest.isSupportedchecked before performing requests - [ ] Matter extension handler implements
commissionDevice(in:onboardingPayload:commissioningID:) - [ ] Action sets tested with the HomeKit Accessory Simulator before shipping
- [ ] Triggers enabled after creation (
trigger.enable(true))
References
- Extended patterns (Matter extension, delegate wiring, SwiftUI): references/matter-commissioning.md
- HomeKit framework
- HMHomeManager
- HMHome
- HMAccessory
- HMRoom
- HMActionSet
- HMTrigger
- MatterSupport framework
- MatterAddDeviceRequest
- MatterAddDeviceExtensionRequestHandler
- Enabling HomeKit in your app
- Adding Matter support to your ecosystem
{
"skill_name": "homekit",
"evals": [
{
"id": 0,
"prompt": "I'm building a HomeKit app that should create a nightly Good Night automation at 10:30 PM. Sketch the Swift guidance for creating the action set, adding a timer trigger that repeats daily, attaching the scene, and enabling the trigger. Call out the HomeKit setup prerequisites and any timing gotchas.",
"expected_output": "HomeKit automation guidance that uses a single HMHomeManager, creates an HMActionSet, creates an HMTimerTrigger with a first fire date at 22:30 and a daily recurrence interval, attaches the action set, enables the trigger, and lists HomeKit capability/usage-description prerequisites.",
"files": [],
"expectations": [
"Uses HomeKit/HMHomeManager, HMHome, HMActionSet, and HMTimerTrigger rather than routing the task to MatterSupport or AccessorySetupKit.",
"Computes the first fire date from hour/minute components such as 22:30.",
"Uses a recurrence interval such as DateComponents(day: 1) for daily repeat instead of reusing hour/minute wall-clock components as the recurrence.",
"Adds the trigger to the home, adds the action set to the trigger, and enables the trigger.",
"Mentions the HomeKit capability and NSHomeKitUsageDescription, and does not access homes before homeManagerDidUpdateHomes."
]
},
{
"id": 1,
"prompt": "We need to add Matter lights into our own smart-home ecosystem from an iOS app. Write the setup checklist and Swift-oriented commissioning outline, including discovery configuration, the extension handler callbacks, optional setup-code handling, and what the app should do after perform() succeeds.",
"expected_output": "MatterSupport commissioning guidance that adds the MatterSupport extension, declares Matter Bonjour services, uses MatterAddDeviceRequest with topology and isSupported, explains conditional setup-payload entitlement/MTRSetupPayload usage, and outlines the extension handler callbacks for credential validation, rooms, commissioning, configuration, and optional network selection.",
"files": [],
"expectations": [
"Adds or verifies a MatterSupport extension target with a MatterAddDeviceExtensionRequestHandler principal handler.",
"Includes NSBonjourServices entries for _matter._tcp, _matterc._udp, and _matterd._udp.",
"Checks MatterAddDeviceRequest.isSupported and builds a topology with ecosystem name and homes before perform().",
"Limits com.apple.developer.matter.allow-setup-payload to callers that provide setup codes programmatically and mentions MTRSetupPayload from the Matter framework for that case.",
"Names extension callbacks such as validateDeviceCredential(_:), rooms(in:), commissionDevice(in:onboardingPayload:commissioningID:), configureDevice(named:in:), and optional Wi-Fi/Thread network selection.",
"Does not present MatterSupport commissioning as ordinary HMHome accessory setup or a lower-level AccessorySetupKit picker flow."
]
},
{
"id": 2,
"prompt": "A product proposal says one Apple accessory guide should cover Matter light onboarding, HomeKit rooms and automations, BLE discovery for a setup-only accessory, GATT control after selection, and joining a temporary Wi-Fi setup network. Write a routing note that assigns each part to the right framework domain and explains what belongs in the HomeKit skill.",
"expected_output": "A boundary-aware routing note that assigns HomeKit/MatterSupport to homes, rooms, HMAccessory characteristics, action sets, triggers, and Matter onboarding; AccessorySetupKit to Bluetooth/Wi-Fi discovery, picker authorization, session events, and migration; CoreBluetooth/GATT to BLE communication after selection; and NetworkExtension to Wi-Fi setup-network joins.",
"files": [],
"expectations": [
"Identifies HomeKit/MatterSupport as the owner for homes, rooms, HMAccessory services/characteristics, action sets, triggers, automations, and Matter commissioning.",
"Limits AccessorySetupKit to Bluetooth/Wi-Fi discovery descriptors, privacy-preserving picker authorization, or ASAccessorySession setup events.",
"Routes post-selection BLE service and characteristic communication to CoreBluetooth/GATT.",
"Routes joining or configuring a temporary Wi-Fi setup network to NetworkExtension.",
"Does not collapse lower-level accessory discovery, GATT communication, or Wi-Fi network joins into HomeKit automation guidance."
]
}
]
}
HomeKit + Matter Extended Patterns
Overflow reference for the homekit skill. Contains advanced patterns that exceed the main skill file's scope.
Contents
- SwiftUI HomeKit Integration
- Full Delegate Wiring
- Service Type Discovery
- Advanced Matter Extension Handler
- Testing with HomeKit Accessory Simulator
SwiftUI HomeKit Integration
HomeKit Store with @Observable
import HomeKit
import SwiftUI
@Observable
@MainActor
final class HomeStore: NSObject {
static let shared = HomeStore()
let homeManager = HMHomeManager()
var homes: [HMHome] = []
var primaryHome: HMHome?
var isAuthorized = false
override init() {
super.init()
homeManager.delegate = self
}
var accessories: [HMAccessory] {
primaryHome?.accessories ?? []
}
var rooms: [HMRoom] {
primaryHome?.rooms ?? []
}
func addHome(name: String) async throws {
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
homeManager.addHome(withName: name) { home, error in
if let error {
continuation.resume(throwing: error)
} else {
continuation.resume()
}
}
}
}
}
extension HomeStore: HMHomeManagerDelegate {
nonisolated func homeManagerDidUpdateHomes(_ manager: HMHomeManager) {
Task { @MainActor in
homes = manager.homes
primaryHome = manager.primaryHome
}
}
nonisolated func homeManager(
_ manager: HMHomeManager,
didUpdate status: HMHomeManagerAuthorizationStatus
) {
Task { @MainActor in
isAuthorized = status.contains(.authorized)
}
}
nonisolated func homeManager(
_ manager: HMHomeManager,
didAdd home: HMHome
) {
Task { @MainActor in
homes = manager.homes
}
}
nonisolated func homeManager(
_ manager: HMHomeManager,
didRemove home: HMHome
) {
Task { @MainActor in
homes = manager.homes
}
}
}Accessory List View
struct AccessoryListView: View {
@State private var homeStore = HomeStore.shared
var body: some View {
NavigationStack {
Group {
if !homeStore.isAuthorized {
ContentUnavailableView(
"HomeKit Access Required",
systemImage: "house.fill",
description: Text("Grant access in Settings to manage your home.")
)
} else if homeStore.accessories.isEmpty {
ContentUnavailableView(
"No Accessories",
systemImage: "lightbulb",
description: Text("Add accessories using the Home app.")
)
} else {
accessoryList
}
}
.navigationTitle(homeStore.primaryHome?.name ?? "Home")
}
}
private var accessoryList: some View {
List {
ForEach(homeStore.rooms, id: \.uniqueIdentifier) { room in
Section(room.name) {
let roomAccessories = homeStore.accessories.filter {
$0.room?.uniqueIdentifier == room.uniqueIdentifier
}
ForEach(roomAccessories, id: \.uniqueIdentifier) { accessory in
AccessoryRow(accessory: accessory)
}
}
}
}
}
}
struct AccessoryRow: View {
let accessory: HMAccessory
var body: some View {
HStack {
Image(systemName: iconName)
VStack(alignment: .leading) {
Text(accessory.name)
.font(.headline)
Text(accessory.isReachable ? "Reachable" : "Not Reachable")
.font(.caption)
.foregroundStyle(accessory.isReachable ? .green : .secondary)
}
}
}
private var iconName: String {
switch accessory.category.categoryType {
case HMAccessoryCategoryTypeLightbulb: return "lightbulb.fill"
case HMAccessoryCategoryTypeThermostat: return "thermometer"
case HMAccessoryCategoryTypeLock: return "lock.fill"
case HMAccessoryCategoryTypeSwitch: return "light.switch.2"
default: return "house.fill"
}
}
}Light Control View
struct LightControlView: View {
let accessory: HMAccessory
@State private var isOn = false
@State private var brightness: Double = 100
private var lightbulbService: HMService? {
accessory.services.first {
$0.serviceType == HMServiceTypeLightbulb
}
}
private var powerCharacteristic: HMCharacteristic? {
lightbulbService?.characteristics.first {
$0.characteristicType == HMCharacteristicTypePowerState
}
}
private var brightnessCharacteristic: HMCharacteristic? {
lightbulbService?.characteristics.first {
$0.characteristicType == HMCharacteristicTypeBrightness
}
}
var body: some View {
VStack {
Toggle("Power", isOn: $isOn)
.onChange(of: isOn) { _, newValue in
powerCharacteristic?.writeValue(newValue) { _ in }
}
if isOn {
Slider(value: $brightness, in: 0...100, step: 1)
.onChange(of: brightness) { _, newValue in
brightnessCharacteristic?.writeValue(
Int(newValue)
) { _ in }
}
Text("Brightness: \(Int(brightness))%")
}
}
.padding()
.task { await readCurrentState() }
}
private func readCurrentState() async {
powerCharacteristic?.readValue { _ in
if let value = powerCharacteristic?.value as? Bool {
isOn = value
}
}
brightnessCharacteristic?.readValue { _ in
if let value = brightnessCharacteristic?.value as? Int {
brightness = Double(value)
}
}
}
}Full Delegate Wiring
HMHomeDelegate
extension HomeStore: HMHomeDelegate {
nonisolated func home(
_ home: HMHome,
didAdd accessory: HMAccessory
) {
accessory.delegate = self
Task { @MainActor in
// Refresh accessory list
}
}
nonisolated func home(
_ home: HMHome,
didRemove accessory: HMAccessory
) {
Task { @MainActor in
// Refresh accessory list
}
}
nonisolated func home(
_ home: HMHome,
didAdd room: HMRoom
) {
Task { @MainActor in
// Refresh room list
}
}
nonisolated func home(
_ home: HMHome,
didUpdateNameFor room: HMRoom
) {
Task { @MainActor in
// Update room name display
}
}
}HMAccessoryDelegate
extension HomeStore: HMAccessoryDelegate {
nonisolated func accessory(
_ accessory: HMAccessory,
service: HMService,
didUpdateValueFor characteristic: HMCharacteristic
) {
Task { @MainActor in
// Update UI for the changed characteristic
let newValue = characteristic.value
print("\(accessory.name).\(characteristic.characteristicType) = \(newValue ?? "nil")")
}
}
nonisolated func accessoryDidUpdateReachability(
_ accessory: HMAccessory
) {
Task { @MainActor in
print("\(accessory.name) reachable: \(accessory.isReachable)")
}
}
nonisolated func accessoryDidUpdateName(
_ accessory: HMAccessory
) {
Task { @MainActor in
// Refresh name display
}
}
}Service Type Discovery
Finding Specific Service Types
// Find all thermostats in the home
let thermostats = home.servicesWithTypes([HMServiceTypeThermostat]) ?? []
for service in thermostats {
let currentTemp = service.characteristics.first {
$0.characteristicType == HMCharacteristicTypeCurrentTemperature
}
let targetTemp = service.characteristics.first {
$0.characteristicType == HMCharacteristicTypeTargetTemperature
}
currentTemp?.readValue { _ in
print("Current: \(currentTemp?.value ?? "?")")
}
}Common Service Types
| Constant | Description |
|---|---|
HMServiceTypeLightbulb | Light control (on/off, brightness, color) |
HMServiceTypeThermostat | Temperature control |
HMServiceTypeLockMechanism | Door lock |
HMServiceTypeGarageDoorOpener | Garage door |
HMServiceTypeSwitch | Generic on/off switch |
HMServiceTypeMotionSensor | Motion detection |
HMServiceTypeTemperatureSensor | Temperature reading |
HMServiceTypeContactSensor | Door/window open/close |
Common Characteristic Types
| Constant | Value Type | Description |
|---|---|---|
HMCharacteristicTypePowerState | Bool | On/off |
HMCharacteristicTypeBrightness | Int (0-100) | Light brightness |
HMCharacteristicTypeHue | Float (0-360) | Light hue |
HMCharacteristicTypeSaturation | Float (0-100) | Light saturation |
HMCharacteristicTypeCurrentTemperature | Float | Celsius reading |
HMCharacteristicTypeTargetTemperature | Float | Celsius target |
HMCharacteristicTypeLockCurrentState | Int | Lock state (0=unsecured) |
HMCharacteristicTypeLockTargetState | Int | Lock target state |
Advanced Matter Extension Handler
Full Handler with Network Selection
import MatterSupport
final class MyMatterHandler: MatterAddDeviceExtensionRequestHandler {
override func validateDeviceCredential(
_ deviceCredential:
MatterAddDeviceExtensionRequestHandler.DeviceCredential
) async throws {
// Validate the Device Attestation Certificate (DAC) against
// your Product Attestation Authority (PAA) root certificates.
let dac = deviceCredential.deviceAttestationCertificate
let pai = deviceCredential.productAttestationIntermediateCertificate
let cd = deviceCredential.certificationDeclaration
// If validation fails, throw an error to reject the device
guard isValidCertificateChain(dac: dac, pai: pai, cd: cd) else {
throw MatterCommissioningError.invalidCredential
}
}
override func rooms(
in home: MatterAddDeviceRequest.Home?
) async -> [MatterAddDeviceRequest.Room] {
// Fetch rooms from your backend for the given home
guard let home else { return [] }
let roomNames = await fetchRoomsFromBackend(homeName: home.displayName)
return roomNames.map { MatterAddDeviceRequest.Room(displayName: $0) }
}
override func configureDevice(
named name: String,
in room: MatterAddDeviceRequest.Room?
) async {
// Save device configuration to your ecosystem backend
await saveDeviceToBackend(
deviceName: name,
roomName: room?.displayName
)
}
override func commissionDevice(
in home: MatterAddDeviceRequest.Home?,
onboardingPayload: String,
commissioningID: UUID
) async throws {
// Commission the device into your Matter fabric
// using the Matter framework (MTRDeviceController)
try await commissionToFabric(
payload: onboardingPayload,
commissioningID: commissioningID
)
}
override func selectWiFiNetwork(
from networks:
[MatterAddDeviceExtensionRequestHandler.WiFiScanResult]
) async throws
-> MatterAddDeviceExtensionRequestHandler.WiFiNetworkAssociation {
// Use the system default network or specify one
return .defaultSystemNetwork
}
override func selectThreadNetwork(
from networks:
[MatterAddDeviceExtensionRequestHandler.ThreadScanResult]
) async throws
-> MatterAddDeviceExtensionRequestHandler.ThreadNetworkAssociation {
return .defaultSystemNetwork
}
}Testing with HomeKit Accessory Simulator
1. Download Additional Tools for Xcode from Apple's developer downloads page 2. Launch HomeKit Accessory Simulator 3. Create simulated accessories (lights, locks, sensors) 4. Pair them with your app running in Simulator or on device
// Enable verbose logging during development
#if DEBUG
import os
let homeKitLog = Logger(subsystem: "com.example.app", category: "HomeKit")
func logAccessories() {
guard let home = homeManager.primaryHome else { return }
for accessory in home.accessories {
homeKitLog.debug("Accessory: \(accessory.name), reachable: \(accessory.isReachable)")
for service in accessory.services {
homeKitLog.debug(" Service: \(service.localizedDescription ?? service.serviceType)")
}
}
}
#endifRelated skills
How it compares
Prefer homekit over generic IoT snippets when implementing Apple HomeKit.framework automations and Matter on iOS with eval-checked Swift APIs.
FAQ
Who is homekit for?
Developers and software engineers working with homekit patterns from the skill documentation.
When should I use homekit?
Control smart-home accessories and commission Matter devices using HomeKit and MatterSupport. Use when managing homes/rooms/accessories, creating action sets or triggers, reading accessory characteristics, onboarding Matter devices, or building a third-party smart-home ecosystem
Is homekit safe to install?
Review the Security Audits panel on this page before installing in production.