Subjects 同時是 Observable 也是 Observer

Publish Subject

訂閱之後才會收到發出的事件。

let subject = PublishSubject<String>()
/// Issue 1 在訂閱之前收不到
subject.onNext("Issue 1")
subject.subscribe { event in
    print(event)
}
subject.onNext("Issue 2")
subject.dispose()
/// Issue 3 在dispose之後收不到
subject.onNext("Issue 3")
/// 印出結果
next(Issue 2)
let subject = PublishSubject<String>()
/// Issue 1 在訂閱之前收不到
subject.onNext("Issue 1")
subject.subscribe { event in
    print(event)
}
subject.onNext("Issue 2")
subject.onCompleted()
/// Issue 3 在completed之後收不到
subject.onNext("Issue 3")
/// 印出結果
next(Issue 2)
completed

Behavior Subject

需給定初始值,因爲訂閱它時,會得到初始值或訂閱前最後一個值。

let subject = BehaviorSubject(value: "Initial value")

subject.subscribe { event in
    print(event)
}

subject.onNext("Issue 1")
/// 印出結果
next(Initial value)
next(Issue 1)
let subject = BehaviorSubject(value: "Initial value")

subject.onNext("Last Issue")

subject.subscribe { event in
    print(event)
}

subject.onNext("Issue 1")
/// 印出結果
next(Last Issue)
next(Issue 1)

Relay Subject

訂閱後可以收到指定數量最新訂閱前發出的事件。

let subject = ReplaySubject<String>.create(bufferSize: 2)

subject.onNext("Issue 1")
subject.onNext("Issue 2")
subject.onNext("Issue 3")

print("[Subscription 1]")
subject.subscribe { event in
    print(event)
}

subject.onNext("Issue 4")
subject.onNext("Issue 5")
subject.onNext("Issue 6")

print("[Subscription 2]")

subject.subscribe { event in
    print(event)
}
/// 印出結果
ubscription 1]
next(Issue 2)
next(Issue 3)
next(Issue 4)
next(Issue 5)
next(Issue 6)
[Subscription 2]
next(Issue 5)
next(Issue 6)

Variables

即將廢除由 BehaviorRelay 取代

為一個可以儲存值的Behavior Subject,我們可以對其屬性存取值。

let variable = Variable("Initial value")

variable.value = "Hello world"

variable.asObservable().subscribe {
    print($0)
}
/// 印出結果
next(Hello world)

訂閱一個字串陣列,當改變陣列內容就會收到事件得到當前陣列的內容。

let variable = Variable([String]())

variable.value.append("Item 1")
variable.asObservable().subscribe {
    print($0)
}

variable.value.append("Item 2")
/// 印出結果
next(["Item 1"])
next(["Item 1", "Item 2"])

BehaviorRelay

需要 pod 'RxCocoa'

  • value 屬性限制為 get-only
  • 更新值使用 accept()
let replay = BehaviorRelay(value: "Item 1")
replay.accept("Hello world")

replay.asObservable()
    .subscribe {
        print($0)
    }
/// 印出結果
next(Hello world)

值的更新為 accept 收到的值,若要累加需先從屬性中取出原本的值。

let replay = BehaviorRelay(value: ["Item 1"])
replay.accept(["Item 2"])
replay.asObservable()
    .subscribe {
        print($0)
    }

replay.accept(replay.value + ["Item 3"])
/// 印出結果
next(["Item 2"])
next(["Item 2", "Item 3"])