Contents

HomeAccessorySettingsProvider

A type that reads and writes an accessory’s settings.

Declaration

@MainActor protocol HomeAccessorySettingsProvider

Overview

A provider has two responsibilities:

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 nil for any value you can’t read reliably.

  • Set custom labels and states on every snapshot. Values such as label, isEnabled, and isHidden are 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.

Topics

Accessing the settings

See Also

Displaying accessory configuration