Monitorowanie stanu urządzenia w iOS

W interfejsach Home API na iOS obserwowanie zmian stanu w domu jest możliwe dzięki użyciu platformy Combine w języku Swift. Obserwowanie zmian w domach, pomieszczeniach, metadanych urządzeń i stanie urządzeń w interfejsach Home API można przeprowadzić za pomocą dowolnego interfejsu API przy użyciu 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ą. W tym celu można użyć pola id udostępnionego dla każdego typu obiektu nadrzędnego w interfejsach Home API.

Jak rozpakować obiekty opcjonalne

Jeśli obiekt jest opcjonalny, użyj if let lub guard, aby bezpiecznie go rozpakować. 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.

Zalecamy, aby obiekty opcjonalne były obsługiwane w ten sposób:

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 pracy z wydawcami w interfejsach Home API. W przypadku poniższych przykładów należy utworzyć instancję 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:

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 konkretnym urządzeniu

Te zmiany na urządzeniu powodują uruchomienie tej kolekcji:

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 określonej cesze na urządzeniu

Używaj dowolnej cechy obsługiwanej 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

Te zmiany typu urządzenia powodują uruchomienie tej kolekcji:

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 następujące zmiany w pomieszczeniu:

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 zdarzeń

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
    // Error getting FanDeviceType
    return Empty<FanDeviceType, Never>().eraseToAnyPublisher()
  }
  .sink { [weak self] fanDeviceType in
    self?.fanDeviceType = fanDeviceType
    self?.updateTileInfo()
  }
}