В API Home для iOS наблюдение за изменениями состояния дома стало возможным благодаря использованию фреймворка Combine на Swift. Наблюдение за изменениями в структурах, комнатах, метаданных и состоянии устройств в API Home можно осуществлять с помощью любого API, использующего HomeDevice
. Это достигается подпиской на издателей, предоставляющих значения из асинхронных событий.
При добавлении, удалении или изменении любого элемента коллекции возвращается последний снимок коллекции.
Разработчик должен определить конкретные изменения, сравнивая этот снимок с более ранней копией. Для этого можно использовать поле id
, предоставленное для каждого родительского типа объекта в API Home .
Как развернуть необязательные объекты
Если объект необязателен, используйте if let
или guard
для безопасного извлечения объекта. Не используйте !
, поскольку !
следует использовать только в том случае, если разработчик точно знает, что объект не может быть равен нулю.
Входной параметр structureID
в этом примере определён как String?
, что означает, что это необязательная строка, которая может быть равна нулю. Эта функция находит объект Structure
на основе входных данных structureID
.
Вот как мы рекомендуем вам обрабатывать необязательные объекты:
func structure(structureID: String?) -> Structure? {
guard let structureID else { return nil }
return structures.first { $0.id == structureID }
}
Как использовать издателей
Ниже приведены несколько базовых примеров работы с издателями в API Home. Для этих примеров необходимо создать экземпляр Home
.
var home: Home?
Прежде чем получить доступ к коллекциям, обязательно разверните их, так как они необязательны:
guard let home else { return nil }
Отслеживание изменений в структуре
Следующие изменения в структуре запускают эту коллекцию:
- Название структуры
home.structures().batched()
.compactMap { $0.first(where: { $0.id = myStructureID} }
.removeDuplicates()
.sink { structure in
if let structure = structure {
print("Structure \(structure.id) updated to \(structure.name)")
}
}
Отслеживание изменений на конкретном устройстве
Следующие изменения в устройстве запускают этот сбор:
- Состояние подключения
- Имя устройства
- Членство в комнате
- Набор поддерживаемых признаков
- Набор поддерживаемых типов
home.devices().batched()
.compactMap { deviceList -> HomeDevice? in
deviceList.filter { $0.name == "Bedroom Lamp"}.first
}
.removeDuplicates()
.sink { lampDevice in
if lampDevice != nil {
print("The bedroom lamp has changed!")
}
}
Отслеживание изменений определенного параметра на устройстве
Используйте любые свойства, поддерживаемые устройством и API Home. Полный список см. в Trait
.
device.types.subscribe(OnOffLightDeviceType.self)
.compactMap { $0.matterTraits.onOffTrait }
.removeDuplicates()
.sink { onOffState in
if let onOffState = onOffState {
print("Got new state update: \(onOffState.onOff)")
}
}
Отслеживание изменений определенного типа на устройстве
Следующие изменения типа устройства запускают этот сбор:
- Изменения любой характеристики в пределах сгенерированного типа устройства
Используйте любой тип устройства Matter , поддерживаемый Home API. Полный список см. в разделе DeviceType
.
device.types.subscribe(DimmableLightDeviceType.self)
.compactMap { $0.matterTraits.levelControlTrait }
.removeDuplicates()
.sink { dimmableLightDevice in
if let dimmableLightDevice = dimmableLightDevice
print("Got new state update! \(levelControlTrait.currentLevel)")
}
}
Отслеживание изменений в помещении в структуре
Следующие изменения в комнате запускают эту коллекцию:
Чтобы отслеживать добавление или удаление устройств из комнаты, используйте запрос devices()
.
home.rooms().batched()
.sink { rooms in
print("Got a new updated set of rooms!")
for room in rooms {
print("Got room #\(room.name)")
}
}
Подписаться на события
В API Home события используются для обнаружения изменений в состоянии устройства.
self.cancellable = self.device.types.subscribe(FanDeviceType.self)
.receive(on: DispatchQueue.main)
.catch { error in
Logger.error("Error getting FanDeviceType: \(error)")
return Empty<FanDeviceType, Never>().eraseToAnyPublisher()
}
.sink { [weak self] fanDeviceType in
self?.fanDeviceType = fanDeviceType
self?.updateTileInfo()
}
}