W interfejsach Home API na iOS obserwowanie zmian stanu w domu jest możliwe dzięki użyciu frameworka Combine w języku Swift. Obserwowanie zmian w strukturach, pomieszczeniach, metadanych urządzeń i stanie urządzeń w interfejsach Home API można przeprowadzić za pomocą dowolnego interfejsu API, korzystając z HomeDevice
. Odbywa się to przez subskrybowanie wydawców udostępniających wartości ze zdarzeń asynchronicznych.
Gdy dowolny element w kolekcji zostanie dodany, usunięty lub zmodyfikowany, zwracana jest najnowsza migawka kolekcji.
Deweloper musi sam określić konkretne zmiany, porównując ten migawkę ze starszą kopią. Do tego celu można użyć pola id
udostępnionego dla każdego typu obiektu nadrzędnego w interfejsach Home API.
Jak rozpakować obiekty opcjonalne
Gdy obiekt jest opcjonalny, użyj if let
lub guard
, aby bezpiecznie rozpakować obiekt. Nie używaj operatora !
, ponieważ nie należy go stosować, chyba że deweloper ma pewność, że obiekt nie może mieć wartości null.!
Parametr wejściowy structureID
w przykładzie jest zdefiniowany jako String?
, co oznacza, że jest to ciąg znaków, który jest opcjonalny i może mieć wartość null. Ta funkcja wyszukuje obiekt Structure
na podstawie danych wejściowych w structureID
.
Oto jak zalecamy obsługiwać obiekty opcjonalne:
func structure(structureID: String?) -> Structure? {
guard let structureID else { return nil }
return structures.first { $0.id == structureID }
}
Jak korzystać z wydawców
Poniżej znajdziesz kilka podstawowych przykładów współpracy z wydawcami w interfejsach Home API. W przypadku poniższych przykładów należy utworzyć instancję elementu Home
.
var home: Home?
Przed uzyskaniem dostępu do kolekcji rozpakuj je, ponieważ są opcjonalne:
guard let home else { return nil }
Śledzenie zmian w strukturze
Ta kolekcja jest aktywowana przez te zmiany w strukturze:
- Nazwa struktury
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)")
}
}
Śledzenie zmian na określonym urządzeniu
Ta kolekcja jest wywoływana przez te zmiany na urządzeniu:
- Stan połączenia
- Nazwa urządzenia
- Subskrypcja Room
- Zestaw obsługiwanych cech
- Zestaw obsługiwanych typów
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!")
}
}
Śledzenie zmian w przypadku konkretnej cechy na urządzeniu
Używaj dowolnych cech obsługiwanych przez urządzenie i interfejsy Home API. Pełną listę znajdziesz w 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)")
}
}
Śledzenie zmian określonego typu na urządzeniu
Ta kolekcja jest wywoływana przez te zmiany typu urządzenia:
- Zmiany w dowolnej cesze w ramach wygenerowanego typu urządzenia
Używaj dowolnego Mattertypu urządzenia obsługiwanego przez interfejsy Home API. Pełną listę znajdziesz w 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)")
}
}
Śledzenie zmian w pokoju w strukturze
Ta kolekcja jest wywoływana przez te zmiany w pokoju:
Aby śledzić, kiedy urządzenia są dodawane do pokoju lub z niego usuwane, użyj devices()
zapytania.
home.rooms().batched()
.sink { rooms in
print("Got a new updated set of rooms!")
for room in rooms {
print("Got room #\(room.name)")
}
}
Subskrybowanie wydarzeń
W interfejsach Home API zdarzenia służą do wykrywania zmian stanu urządzenia.
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()
}
}