Subjects - wurzelsand/swift-memos GitHub Wiki

Subjects

Themen

  • Error ableiten
  • Subscriptions speichern
  • PassthroughSubject und CurrentValueSubject
  • AnyPublisher

Aufgabe 1: PassthroughSubject

Erstelle ein PassthroughSubject, verschicke darüber die Strings "Hello" und "World" und fange sie über eine Subscription auf. Beende die Subscription mit dem Senden eines Fehlers vom Typ MyError:

enum MyError: Error {
    case myFailure
}

Ausführung

import Combine

enum MyError: Error {
    case myFailure
}

var subscriptions = Set<AnyCancellable>()
let subject = PassthroughSubject<String, MyError>()
subject
    .sink(receiveCompletion: { print("Completion:", $0)},
          receiveValue: { print("Received:", $0)})
    .store(in: &subscriptions)

subject.send("Hello")
subject.send("World")
subject.send(completion: .failure(.myFailure))

Ausgabe:

Received: Hello
Received: World
Completion: failure(Xxxxx.MyError.myFailure)
Program ended with exit code: 0

Aufgabe 2: CurrentValueSubject

Ändere das PassthroughSubject in ein CurrentValueSubject. Prüfe den letzten Wert des Subjects bevor du ihn mit dem Fehler beendest.

Ausführung

import Combine

enum MyError: Error {
    case myFailure
}

var subscriptions = Set<AnyCancellable>()
let subject = CurrentValueSubject<String, MyError>("")
subject
    .sink(receiveCompletion: { print("Completion:", $0)},
          receiveValue: { print("Received:", $0)})
    .store(in: &subscriptions)

subject.send("Hello")
subject.send("World")
print(subject.value)
subject.send(completion: .failure(.myFailure))

Ausgabe:

Received: 
Received: Hello
Received: World
World
Completion: failure(Xxxxx.MyError.myFailure)
Program ended with exit code: 0

Anmerkungen

  • Anstatt einen Wert zu senden, kann man den Wert eines CurrentValueSubjects direkt ändern: subject.value = "Hello".

Aufgabe 3: Type erasure

Ändere die Ausführung von Aufgabe 1 so um, dass nicht mehr das Subject seine Nachrichten überwacht, sondern ein Publisher vom Typ AnyPublisher.

Ausführung

import Combine

enum MyError: Error {
    case myFailure
}

var subscriptions = Set<AnyCancellable>()
let subject = PassthroughSubject<String, MyError>()
let publisher = subject.eraseToAnyPublisher()
publisher
    .sink(receiveCompletion: { print("Completion:", $0)},
          receiveValue: { print("Received:", $0)})
    .store(in: &subscriptions)

subject.send("Hello")
subject.send("World")
subject.send(completion: .failure(.myFailure))

Anmerkungen

  • publisher kann nun nur noch Subscriptions vergeben, selbst aber keine Nachrichten über send verschicken.