HomeAccessorySettingsProvider
A type that reads and writes an accessory’s settings.
Declaration
@MainActor protocol HomeAccessorySettingsProviderOverview
A provider has two responsibilities:
In settings(context:for:), it reads the accessory and returns a fresh snapshot of its settings.
In settingsDidChange(changes:context:for:), it applies the person’s changes to the accessory.
The provider itself doesn’t store any setting values.
Declare your settings in a HomeAccessorySettingsContainer, and create a new instance of it in settings(context:for:).
When a person changes a setting, settingsDidChange(changes:context:for:) receives the new values keyed by setting identifier. Cast each value to match its setting: Bool for a toggle, NSNumber for a range, and String for an enumeration (its raw value) or a text field. Information settings are read-only, so they never appear in the dictionary.
For example, the following provider manages a thermostat’s eco mode setting:
struct ThermostatProvider: HomeAccessorySettingsProvider {
func settings(context: ThermostatContext, for accessory: HMAccessory) async throws -> ThermostatSettings {
// Build a fresh snapshot each call; pass nil for anything you couldn't read.
ThermostatSettings(ecoMode: try await context.webService.isEcoOn())
}
func settingsDidChange(changes: [String: Any], context: ThermostatContext, for accessory: HMAccessory) async throws {
for (id, value) in changes {
switch id {
case ThermostatSettings.ecoModeID:
try await context.webService.setEco(value as? Bool ?? false) // await the write — see note
default:
break
}
}
}
}When implementing a provider, do the following:
Keep your implementation of settings(context:for:) fast. The framework calls it when the settings appear and again after every change.
Write only the settings you receive in settingsDidChange(changes:context:for:). Don’t rebuild or return state there.
Await your device write before returning. The framework reads the settings again immediately afterward.
Return
nilfor any value you can’t read reliably.Set custom labels and states on every snapshot. Values such as
label,isEnabled, andisHiddenare part of each snapshot, so a value you set once on a cached container doesn’t persist.Assign complete labels. Assigning a string, such as
$ecoMode.label = "New Title", clears the detailedLabel. To preserve it, assign both values.Use unique setting identifiers across all your providers. The framework uses identifiers to route each change to the provider that owns the setting.