새소식

iOS/RxSwift

[RxSwift] Combine Operator

  • -

startwith : 초기 값을 받는지 여부, 우선순위로 맨 앞에 Element가 추가되고 위치의 제약을 받지 않음

let yellow = Observable.of("a", "b", "c")
yellow
    .startWith("Teacher")
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)
    
// Teacher
// a
// b
// c

concat : Observable들을 연결

let yellow1 = Observable.of("a", "b", "c")
let teacher1 = Observable<String>.of("Teacher")
let line = Observable
    .concat([teacher1, yellow1])

line.subscribe(onNext: {
    print($0)
})
.disposed(by: disposeBag)

// Teacher
// a
// b
// c

concatMap : flatMap과 concat이 합쳐진 개념, 순서가 보장되어 있음

let kindergarden: [String : Observable<String>] = [
    "yellow" : Observable.of("a", "b", "c"),
    "blue"   : Observable.of("1", "2"),
]

Observable.of("yellow", "blue")
    .concatMap{ color in
        kindergarden[color] ?? .empty() // 없으면 empty()
    }
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

// a
// b
// c
// 1
// 2

merge : 여러 Observerable들을 순서가 보장되지 않게 하나의 Observable로 결합

let north = Observable.from(["평양", "신의주", "개성"])
let south = Observable.from(["서울", "인천", "대구"])

Observable.of(north, south)
    .merge()
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag
    
// 평양
// 신의주
// 서울
// 개성
// 인천
// 대구

combineLastest : Subject들을 결합

let firstName = PublishSubject<String>()
let lastName = PublishSubject<String>()

let name = Observable   // 성과 이름을 조합하여 값들을 결합
    .combineLatest(firstName, lastName, resultSelector: {
        firstName, lastName in
        firstName + lastName
    })
name.subscribe(onNext: {
    print($0)
})
.disposed(by: disposeBag)

firstName.onNext("Tomas")   // firstname 최신값
lastName.onNext("Kim")
lastName.onNext("Kang")     // lastname 최신값
firstName.onNext("Jimmy")
firstName.onNext("Lee")

// TomasKim
// TomasKang
// JimmyKang
// LeeKang

zip : 지정된 함수를 통해 여러 Observable의 방출과 함께 결합하고 함 수의 결과를 기반으로 각 조합에 대하여 Single items를 방출

enum Result{
    case win
    case lose
}

let battle1 = Observable<Result>.of(.win, .lose, .win, .win)
let player1 = Observable<String>.of("KOR", "USA", "JPN", "ENG")

let battleResult = Observable
    .zip(battle1, player1){ result, player in
        // 둘 중 하나의 Observable이 종료되면 종료
        return player + "선수" + "\(result)"
    }

battleResult
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

// KOR선수win
// USA선수lose
// JPN선수win
// ENG선수win

withLastestFrom : 두 Observable 중 첫 Observable에서 item이 방출될 때마다 그 item을 
두 번째 Observable의 가장 최근 item과 결합하여 방출

let trigger = PublishSubject<Void>()
let runner = PublishSubject<String>()

// trigger에 적용된 withLatestFrom 안에 있는 최근값이 작동
trigger
    .withLatestFrom(runner)
//    .distinctUntilChanged() sample과 같음
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

runner.onNext("1번 선수 출발")
runner.onNext("1,2번 선수 출발")
runner.onNext("1,2,3번 선수 출발")

trigger.onNext(print("탕"))
trigger.onNext(print("탕탕"))

// 탕
// 1,2,3번 선수 출발
// 탕탕
// 1,2,3번 선수 출발

sample : 주기적인 시간 간격 내에 Observable에서 방출한 가장 최근 항목을 배출

let start = PublishSubject<Void>()
let f1Player = PublishSubject<String>()

f1Player
    .sample(start) // 가장 최근 값이 한번만 작동
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

f1Player.onNext("1번 차")
f1Player.onNext("1번 차, 2번 차")
f1Player.onNext("1번 차, 2번 차, 3번 차")
start.onNext(Void())
start.onNext(Void())
start.onNext(Void())

// 1번 차, 2번 차, 3번 차

amb : 두 개 이상의 Observable에서 첫 번 째 Observable에서만 모든 항목 방출

let bus1 = PublishSubject<String>()
let bus2 = PublishSubject<String>()

let busStop = bus1.amb(bus2) // 두 개중 시작하는 것을 보고 결정
busStop.subscribe(onNext: {
    print($0)
})
.disposed(by: disposeBag)

bus1.onNext("버스 1 승객 0")
bus1.onNext("버스 1 승객 3")
bus2.onNext("버스 2 승객 2")
bus1.onNext("버스 1 승객 3")
bus2.onNext("버스 2 승객 3")

// 버스 1 승객 0
// 버스 1 승객 3
// 버스 1 승객 3

switchLatest : 지정한 Sequence만 방출

let stu1 = PublishSubject<String>()
let stu2 = PublishSubject<String>()
let stu3 = PublishSubject<String>()

let shakeHand = PublishSubject<Observable<String>>()

// switchLastest에 들어오는 제일 최신의 Sequence만 구독 나머지 event는 무시
let classRoom = shakeHand.switchLatest()

classRoom
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

shakeHand.onNext(stu1)
stu1.onNext("학생1: 1")
stu2.onNext("학생2")

shakeHand.onNext(stu3)
stu2.onNext("학생2")
stu3.onNext("학생3: 1")

// 학생1: 1
// 학생3: 1

reduce : Swift reduce 개념과 동일, Observable이 배출한 각 항목에 순차적으로 함수를 적용하고 최종값을 방출

Observable.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
//    .reduce(0, accumulator: { summary, newValue in
//        return summary + newValue
//    })
//    .reduce(0){ summary, newValue in
//        return summary + newValue
//    }
    .reduce(0, accumulator: +) // 위 두가지와 동일한 표현
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

// 55

scan : reduce와 유사하지만 return이 Observable 값이 누적되어 출력

Observable.from((1...10))
    .scan(0, accumulator: +)    // 값이 들어올 때마다 변형된 값들을 방출
    .subscribe(onNext:{
        print($0)
    })
    .disposed(by: disposeBag)
// 1
// 3
// 6
// 10
// 15
// 21
// 28
// 36
// 45
// 55

 

출처

패스트캠퍼스 | 30개 프로젝트로 배우는 iOS 앱개발 with Swift 초격차 패키지 Online
728x90

'iOS > RxSwift' 카테고리의 다른 글

[RxSwift] TimeBasedOperator  (0) 2023.10.03
[RxSwift] Traits  (0) 2023.09.18
[RxSwift] Subject  (0) 2023.09.16
[RxSwift] Observable  (0) 2023.09.10
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.