Gerätestatus unter iOS überwachen

In den Home APIs für iOS können Änderungen am Status im Zuhause mithilfe des Combine-Frameworks in Swift beobachtet werden. Änderungen an Strukturen, Räumen, Gerätemetadaten und Gerätestatus in den Home APIs können mit jeder API mithilfe von HomeDevice beobachtet werden. Dazu werden Publisher abonniert, die Werte aus asynchronen Ereignissen bereitstellen.

Wenn ein Element in einer Sammlung hinzugefügt, gelöscht oder geändert wird, wird der aktuelle Snapshot der Sammlung zurückgegeben.

Es liegt in der Verantwortung des Entwicklers, die spezifischen Änderungen abzuleiten, indem er diesen Snapshot mit einer älteren Kopie vergleicht. Das id Feld, das für jeden übergeordneten Objekttyp in den Home APIs bereitgestellt wird, kann für diesen Zweck verwendet werden.

Optionale Objekte entpacken

Wenn ein Objekt optional ist, verwenden Sie if let oder guard, um das Objekt sicher zu entpacken. Verwenden Sie nicht !, da ! nur verwendet werden sollte, wenn der Entwickler sicher ist, dass das Objekt nicht „nil“ sein kann.

Der Eingabeparameter structureID im Beispiel ist als String? definiert. Das bedeutet, dass es sich um einen optionalen String handelt, der „nil“ sein kann. Diese Funktion sucht das Structure-Objekt anhand der Eingabe in structureID.

Wir empfehlen, optionale Objekte so zu verarbeiten:

func structure(structureID: String?) -> Structure? {
    guard let structureID else { return nil }
    return structures.first { $0.id == structureID }
  }

Publisher verwenden

Im Folgenden finden Sie einige grundlegende Beispiele für die Verwendung von Publishern in den Home APIs. Für die folgenden Beispiele muss eine Instanz von Home erstellt werden.

var home: Home?

Bevor Sie auf Sammlungen zugreifen, müssen Sie sie entpacken, da sie optional sind:

guard let home else { return nil }

Änderungen an einer Struktur verfolgen

Die folgenden Änderungen an einer Struktur lösen diese Sammlung aus:

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)")
    }
  }

Änderungen an einem bestimmten Gerät verfolgen

Die folgenden Änderungen an einem Gerät lösen diese Sammlung aus:

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!")
    }
  }

Änderungen an einer bestimmten Eigenschaft auf einem Gerät verfolgen

Verwenden Sie eine beliebige Eigenschaft, die vom Gerät und den Home APIs unterstützt wird. Eine vollständige Liste finden Sie unter 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)")
    }
  }

Änderungen an einem bestimmten Typ auf einem Gerät verfolgen

Die folgenden Änderungen an einem Gerätetyp lösen diese Sammlung aus:

Verwenden Sie einen beliebigen Matter Gerätetyp, der von den Home APIs unterstützt wird. Eine vollständige Liste finden Sie unter 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)")
    }
  }

Änderungen an einem Raum in einer Struktur verfolgen

Die folgenden Änderungen an einem Raum lösen diese Sammlung aus:

Verwenden Sie die devices() Abfrage, um zu verfolgen, wann Geräte zu einem Raum hinzugefügt oder daraus entfernt werden.

home.rooms().batched()
  .sink { rooms in
    print("Got a new updated set of rooms!")
    for room in rooms {
      print("Got room #\(room.name)")
    }
  }

Ereignisse abonnieren

In den Home APIs werden Ereignisse verwendet, um Änderungen am Status eines Geräts zu erkennen.

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()
  }
}