HomeKit enables your app to control smart home accessories. Learn to integrate with HomeKit and create home automation.
HomeKit Setup
Configure HomeKit
- 1Go to Project Settings > Signing & Capabilities
- 2Add "HomeKit" capability
- 3Enable HomeKit in Entitlements
Import HomeKit
swift
import HomeKit
import SwiftUI
class HomeManager: NSObject, ObservableObject, HMHomeManagerDelegate {
private let homeManager = HMHomeManager()
@Published var homes: [HMHome] = []
@Published var accessories: [HMAccessory] = []
@Published var authorizationStatus: HMHomeManagerAuthorizationStatus = .determined
override init() {
super.init()
homeManager.delegate = self
}
func requestAuthorization() {
homeManager.requestAuthorization { status in
DispatchQueue.main.async {
self.authorizationStatus = status
}
}
}
func loadHomes() {
homes = homeManager.homes
updateAccessories()
}
func updateAccessories() {
guard let home = homes.first else { return }
accessories = home.accessories ?? []
}
}Accessories
Discover Accessories
swift
extension HomeManager {
func addAccessory(completion: @escaping (Bool) -> Void) {
homeManager.addAndSetupAccessories { error in
if let error = error {
print("Error adding accessory: \(error)")
completion(false)
} else {
self.loadHomes()
completion(true)
}
}
}
func removeAccessory(_ accessory: HMAccessory, from home: HMHome) {
home.removeAccessory(accessory) { error in
if let error = error {
print("Error removing accessory: \(error)")
} else {
self.updateAccessories()
}
}
}
}Services and Characteristics
Control Accessories
swift
class AccessoryController: ObservableObject {
@Published var isOn = false
@Published var brightness = 0.5
func toggleLight(_ accessory: HMAccessory) {
guard let service = accessory.services.first(where: { $0.serviceType == .lightbulb }) else {
return
}
guard let powerCharacteristic = service.characteristics.first(where: { $0.characteristicType == .powerState }) else {
return
}
let targetValue: Bool = !isOn
powerCharacteristic.writeValue(targetValue) { error in
if let error = error {
print("Error toggling light: \(error)")
} else {
DispatchQueue.main.async {
self.isOn = targetValue
}
}
}
}
func setBrightness(_ value: Int, for accessory: HMAccessory) {
guard let service = accessory.services.first(where: { $0.serviceType == .lightbulb }) else {
return
}
guard let brightnessCharacteristic = service.characteristics.first(where: { $0.characteristicType == .brightness }) else {
return
}
brightnessCharacteristic.writeValue(value) { error in
if let error = error {
print("Error setting brightness: \(error)")
} else {
DispatchQueue.main.async {
self.brightness = Double(value) / 100.0
}
}
}
}
}Home Automation
Create Triggers
swift
extension HomeManager {
func createTrigger(name: String, condition: HMTriggerCondition, actionSet: HMActionSet) {
guard let home = homes.first else { return }
let trigger = HMTrigger(name: name, conditions: [condition], actions: [actionSet])
home.addActionSet(actionSet) { error in
if let error = error {
print("Error adding action set: \(error)")
} else {
home.addTrigger(trigger) { error in
if let error = error {
print("Error adding trigger: \(error)")
}
}
}
}
}
func createTimeTrigger(hour: Int, minute: Int, actionSet: HMActionSet) {
let dateComponents = DateComponents(hour: hour, minute: minute)
let condition = HMEventTrigger(condition: HMCalendarEvent(condition: dateComponents))
createTrigger(
name: "Time Trigger",
condition: condition,
actionSet: actionSet
)
}
}Action Sets
Define Actions
swift
extension HomeManager {
func createActionSet(name: String, actions: [HMAction]) -> HMActionSet {
let actionSet = HMActionSet(name: name, actions: actions)
return actionSet
}
func createLightAction(accessory: HMAccessory, isOn: Bool, brightness: Int) -> HMAction? {
guard let service = accessory.services.first(where: { $0.serviceType == .lightbulb }) else {
return nil
}
var actions: [HMAction] = []
// Power action
if let powerCharacteristic = service.characteristics.first(where: { $0.characteristicType == .powerState }) {
let powerAction = HMCharacteristicAction(
characteristic: powerCharacteristic,
value: isOn
)
actions.append(powerAction)
}
// Brightness action
if let brightnessCharacteristic = service.characteristics.first(where: { $0.characteristicType == .brightness }) {
let brightnessAction = HMCharacteristicAction(
characteristic: brightnessCharacteristic,
value: brightness
)
actions.append(brightnessAction)
}
return actions.count > 0 ? HMActionSet(name: "Light Actions", actions: actions) : nil
}
}Characteristic Monitoring
Listen for Changes
swift
class CharacteristicMonitor {
func monitorCharacteristic(_ characteristic: HMCharacteristic) {
characteristic.enableNotification { error in
if let error = error {
print("Error enabling notification: \(error)")
return
}
// Add observer
NotificationCenter.default.addObserver(
forName: HMCharacteristicValueDidChangeNotification,
object: characteristic,
queue: .main
) { notification in
if let updatedCharacteristic = notification.object as? HMCharacteristic {
self.handleCharacteristicChange(updatedCharacteristic)
}
}
}
}
func handleCharacteristicChange(_ characteristic: HMCharacteristic) {
if let value = characteristic.value as? Bool {
print("Power state changed: \(value)")
} else if let value = characteristic.value as? Int {
print("Value changed: \(value)")
}
}
}Rooms and Zones
Organize Accessories
swift
extension HomeManager {
func createRoom(name: String, in home: HMHome) {
home.addRoom(withName: name) { room, error in
if let room = room {
print("Room created: \(room.name)")
} else {
print("Error creating room: \(error)")
}
}
}
func addAccessory(_ accessory: HMAccessory, to room: HMRoom) {
room.addAccessory(accessory) { error in
if let error = error {
print("Error adding accessory to room: \(error)")
}
}
}
func createZone(name: String, in home: HMHome, rooms: [HMRoom]) {
home.addZone(withName: name, rooms: rooms) { zone, error in
if let zone = zone {
print("Zone created: \(zone.name)")
} else {
print("Error creating zone: \(error)")
}
}
}
}Siri Integration
Custom Siri Commands
swift
extension HomeManager {
func createCustomSiriPhrase(name: String, phrase: String, actionSet: HMActionSet) {
guard let home = homes.first else { return }
let trigger = HMAccessoryControlTrigger(
name: name,
conditions: [],
actionSets: [actionSet]
)
home.addTrigger(trigger) { error in
if let error = error {
print("Error adding Siri trigger: \(error)")
} else {
print("Siri phrase added: \(phrase)")
}
}
}
}SwiftUI Integration
Home Control View
swift
struct HomeControlView: View {
@StateObject private var homeManager = HomeManager()
@StateObject private var accessoryController = AccessoryController()
var body: some View {
NavigationView {
List(homeManager.accessories) { accessory in
AccessoryRow(
accessory: accessory,
controller: accessoryController
)
}
.navigationTitle("Home")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Add Accessory") {
homeManager.addAccessory { success in
print("Accessory added: \(success)")
}
}
}
}
}
.task {
homeManager.requestAuthorization()
homeManager.loadHomes()
}
}
}
struct AccessoryRow: View {
let accessory: HMAccessory
let controller: AccessoryController
var body: some View {
HStack {
VStack(alignment: .leading) {
Text(accessory.name ?? "Unknown")
.font(.headline)
Text(accessory.room?.name ?? "Unassigned")
.font(.caption)
.foregroundColor(.secondary)
}
Spacer()
Toggle("", isOn: Binding(
get: { controller.isOn },
set: { _ in controller.toggleLight(accessory) }
)
}
}
}Best Practices
- 1Authorization: Request authorization appropriately
- 2Error Handling: Handle HomeKit errors gracefully
- 3UI: Provide intuitive control interface
- 4Performance: Optimize for performance
- 5Testing: Test with real HomeKit accessories
- 6Updates: Handle accessory updates
- 7Siri: Implement custom Siri commands
- 8Security: Maintain security best practices
HomeKit enables seamless smart home integration!