[Swift]RxSwift 기초 문법
RxSwift 기초 문법 공부한 것을 정리하고자 만든 게시물입니다.
부족한 부분이 있다면 꼭 말씀해주세요 😁
이 게시물 역시 참고 용도로 가볍게 봐주시면 감사합니다 😏

RxSwift 기초 문법 🍎

Observable

just

  • just 정의로는 "Returns an observable sequence that contains a single element" 라고 되어있다.
  • 해석하면 "단일 요소를 포함하는 관찰 가능한 시퀀스를 반환합니다" 라고 한다.
  • 쉽게 말해 하나의 요소만 포함하는 Observable Sequence를 생성한다고 보면 된다.
let observable = Observable.just(1)

 

of

  • of 정의로는 "This method creates a new Observable instance with a variable number of elements" 라고 되어있다.
  • 해석하면 "이 메서드는 다양한 수의 요소를 가진 새로운 Observable 인스턴스를 생성합니다" 라고 한다.
  • 쉽게 말해 여러 개의 요소를 가진 Observable 인스턴스를 생성한다고 보면 된다.
let observable2 = Observable.of(1,2,3)		// Int
let observable3 = Observable.of([1,2,3])	// [Int]

 

from

  • from 정의로는 "Converts an array to an observable sequence" 라고 되어있다.
  • 해석하면 "배열을 관찰 가능한 시퀀스로 변환" 라고 한다.
  • 쉽게 말해 배열 형태의 Observable Sequence를 생성한다고 보면 된다.
let observable4 = Observable.from([1,2,3,4,5])

 

Subscribe

  • Observable에 Observer를 연결하는 접착제
  • Observable에서 아이템이 방출, 에러 혹은 완료 알림을 받기 위해서는 반드시 처음에 이 연산자를 Observable에 사용해 구독해야만 가능하다.

 

Need Unwrapping 📁

  • 언래핑이 필요한 경우
let observable = Observable.from([1,2,3,4,5])

observable.subscribe { event in
    if let element = event.element {
        print("DEBUG: need unwrapping, element is \(element)")
    }
}

// DEBUG: need unwrapping, element is 1
// DEBUG: need unwrapping, element is 2
// DEBUG: need unwrapping, element is 3
// DEBUG: need unwrapping, element is 4
// DEBUG: need unwrapping, element is 5

 

Don't need Unwrapping 📂

  • 언래핑이 필요 없는 경우
let observable = Observable.from([1, 2, 3, 4, 5])

observable.subscribe(onNext: { element in
    print("DEBUG: need not unwarapping, element is \(element)")
})

// DEBUG: need not unwarapping, element is 1
// DEBUG: need not unwarapping, element is 2
// DEBUG: need not unwarapping, element is 3
// DEBUG: need not unwarapping, element is 4
// DEBUG: need not unwarapping, element is 5

 

Dispose

  • 메모리의 효율성을 위해 구독을 취소하는 메서드
let subscription = observable.subscribe(onNext: { element in
    print("DEBUG: element is \(element)")
})

subscription.dispose()		// 구독 취소

 

DisposeBag

  • 한 번에 모든 Observer를 지우기 위한 Dispose 가방
  • 각각의 비동기 작업들을 DisposeBag에 담아두고 한 번에 처분하는 형식
  • 여러 비동기 작업들을 하나씩 관리하기 힘들기 때문!!
let disposeBag = DisposeBag()

Observable.of("A", "B", "C")
    .subscribe {
        print("DEBUG: value is \($0)")
    }.disposed(by: disposeBag)
  • When dispose?
    • 해당 class가 deinit(메모리 해제)되면 자동으로 해제

 

 

 

Create

  • 직접 Observable 시퀀스를 생성할 때 사용
  • 포인트는 일회성이기 때문에 반드시 재생성되지 않도록 반환을 해줘야 한다.
Observable<String>.create { observer in

    observer.onNext("A")
    observer.onCompleted()
    observer.onNext("?")    // 호출 안됨, onCompleted 선언

    // 일회성이기 때문에 반드시 다시 생성되지 않도록 반환하기
    return Disposables.create()
}.subscribe {
    print("DEBUG: subscribe is \($0)")
} onError: {
    print("DEBUG: onError is \($0)")
} onCompleted: {
    print("DEBUG: onCompleted")
} onDisposed: {
    print("DEBUG: onDisposed")
}

// DEBUG: subscribe is A
// DEBUG: onCompleted
// DEBUG: onDisposed

 

PublishSubject

  • Subscribe한 이후부터 발생하는 이벤트를 처리한다.
let disposeBag = DisposeBag()

let subject = PublishSubject<String>()

subject.onNext("Event 1")       // 구독 전이라 Event 1은 출력되지 않는다.

subject.subscribe { event in
    print("DEBUG: event is \(event)")
}

subject.onNext("Event 2")
subject.onNext("Event 3")

subject.onCompleted()

subject.dispose()

subject.onNext("Event 4")       // Dispose로 인해 더 이상 구독되지 않아 출력 X

// DEBUG: event is next(Event 2)
// DEBUG: event is next(Event 3)
// DEBUG: event is completed

 

 

BehaviorSubject

  • 초기값을 가지고 생성된다.
  • 구독 전 이벤트 중 최신 이벤트만 전달받는다.
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "Initial value")

subject.onNext("Start event")       // Event 1이 가장 최신이므로 Start event는 전달 X
subject.onNext("Event 1")

subject.subscribe { event in
    print("DEBUG: event is \(event)")
}

subject.onNext("Event 2")
subject.onNext("Event 3")

// DEBUG: event is next(Event 1)
// DEBUG: event is next(Event 2)
// DEBUG: event is next(Event 3)

 

ReplaySubject

  • 버퍼의 크기만큼 구독 전 최신 이벤트를 저장하고 있을 수 있다.
let disposeBag = DisposeBag()

//// 버퍼의 크기만큼만 구독 전 최신 이벤트를 전달 받을 수 있다.
let subject = ReplaySubject<String>.create(bufferSize: 2)

subject.onNext("Event 1")           // 버퍼 크기가 2이므로, Event 1은 발생 X
subject.onNext("Event 2")
subject.onNext("Event 3")

subject.subscribe { event in
    print("DEBUG: event is \(event)")
}

// DEBUG: event is next(Event 2)
// DEBUG: event is next(Event 3)

 

Relay

  • Relay Class는 RxCocoa4에 구현되어있다.
  • 클래스로는 PulishRelay와 BehaviorRelay 클래스가 존재한다.
  • Subject는 .completed와 .error가 발생하면 종료되지만, Relay는 발생하지 않고, Dispose가 될 때까지 계속 작동한다.
  • 이에 UI Event에서 사용하기에 적절하다고 한다.

 

PublishRelay

  • PublishSubject의 Wrapper 클래스로, PublishSubject의 특성처럼 구독 이후의 발생하는 이벤트들만 알 수 있다.

 

BehaviorRelay

  • BehaviorSubject의 Wrapper 클래스로, .value를 통해 현재 값을 가져올 수 있다.
  • variable이 Deprecate 되면서 이 BehaviorRelay를 사용하게 된다.

 

toArray

  • 각각 원소가 아닌 배열 자체를 반환받고 싶을 때 사용한다.
let disposeBag = DisposeBag()

Observable.of(1,2,3,4,5)
    .toArray()
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

// [1, 2, 3, 4, 5]

let disposeBag = DisposeBag()

Observable.of(1,2,3,4,5)
//    .toArray()
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

// 1
// 2
// 3
// 4
// 5

 

flatMap

  • 각각의 요소를 구독할 수 있고, 변경될 때마다 알려준다.
  • 리턴에 observable을 반환해준다.
let disposeBag = DisposeBag()

struct Student {
    var score: BehaviorRelay<Int>
}

let john = Student(score: BehaviorRelay(value: 75))
let mary = Student(score: BehaviorRelay(value: 95))

let student = PublishSubject<Student>()

student.asObserver()
    .flatMap { $0.score.asObservable() }
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

student.onNext(john)
john.score.accept(100)

student.onNext(mary)
mary.score.accept(80)

john.score.accept(59)

// 75
// 100
// 95
// 80
// 59

 

flatMapLatest

  • 가장 최근에 구독한 객체의 요소만 반환해준다.
let disposeBag = DisposeBag()

struct Student {
    var score: BehaviorRelay<Int>
}

let john = Student(score: BehaviorRelay(value: 75))
let mary = Student(score: BehaviorRelay(value: 95))

let student = PublishSubject<Student>()

student.asObservable()
    .flatMapLatest { $0.score.asObservable() }
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

student.onNext(john)
john.score.accept(100)

student.onNext(mary)
john.score.accept(73)		// 무시
mary.score.accept(52)

// 75
// 100
// 95
// 52

'Udemy.zip' 카테고리의 다른 글

[Swift] Firebase 기능  (0) 2022.03.25
[Swift]Table View 이슈  (0) 2022.03.05
[Swift]Model 동기화  (0) 2022.02.27
[Swift]ActionSheet-Protocol  (0) 2022.02.25