💡 RxSwift
관찰 가능한 순차적 형태와 함수 형태의 연산자를 통해 비동기 이벤트를 위한 코드
사용자가 언제 어떠한 버튼을 누를지 알 수 없기 때문에 비동기 처리가 필요하다.
비동기 방식으로 이벤트를 전달하고 전달 받기 위해 RxSwift를 사용하는 것이다.
이벤트를 생성하고 전달하는 Observable
이벤트를 받아 처리하는 Observer
Subscribe를 하여 Observer가 이벤트를 받는다.
💡 Observable과 Observer
이벤트 시퀀스를 비동기적으로 생성한다.
Observable을 통해 이벤트를 방출(emit)할 수 있다.
Observable과 Observer를 통해 Stream(데이터의 흐름)을 통제하고, Operator(just, of, take..)를 통해 ㄴㄴStream을 변경, 조작할 수 있다.
Observable이 전달할 수 있는 이벤트
- Next
- Completed
- Error
Observable은 subscribe를 하지 못하기 때문에 이벤트를 방출만 할 수 있고, 이벤트는 처리하지 못한다.
Observer 또한 받은 이벤트를 다른 Observer에게 전달하지 못한다.
💡 Subject
Subject를 통해 Observable과 Observer가 동시에 같은 역할을 할 수 있다.
Subscribe는 이벤트에 대한 Emit과 Subscribe를 모두 할 수 있다.
Subject의 종류
- PublishSubject
- BehaviorSubject
- ReplaySubject
- AsyncSubject
✅ publishSubject
- 초기 값을 가지고 있지 않다.
let isOn = PublishSubject<Bool>()
isOn.onNext(true)
: onNext로 default 값 설정- 구독하기 전에 이벤트를 전달하면 이벤트를 받지 못한다.
이벤트 전달 순서
구독하기 전에 이벤트를 전달하였기 때문에 이벤트를 받지 못한다.
구독한 후 이벤트를 전달해야 한다.
publishSubject는 completed가 전달되면 dispose를 수행하여 구독을 해제한다.
✅ BehaviorSubject
자기가 가지고 있는 데이터를 변경한다. → observable이 Observer의 역할도 수행
subscribe 이전에 emit한 이벤트가 있다면, 가장 최근에 전달된 이벤트 하나를 전달받을 수 있다.
없다면 초기값 전달
BehaviorSubject는 subcribe 이전에 가장 최신에 방출한 이벤트 하나를 버퍼에 저장하고 있다.
🔎 BehaviorSubject와 PublishSubject 차이
- 초기 값 설정 여부
- 구독 이전의 next 이벤트 처리 방식
✅ ReplaySubject
subscribe 이전에 전달한 이벤트를 buffersize 만큼 가지고 있다가, subscribe 하고 나면 방출한다.
오류가 발생하더라도 메모리에서 보유하고 있는 이벤트를 emit하고 error를 notification 한다.
너무 큰 buffersize는 메모리 부하가 발생할 수 있다.
✅AsyncSubject
complete이벤트를 만나야 이벤트가 emit 된다.
다른 subject와는 다르게 구독 즉시 이벤트 전달이 되지 않는다.
complete가 발생했을 때 가장 최근 시점의 next 이벤트 하나가 방출된다.
💡 Relay
UI 이벤트에 대한 코드를 구현할 때에는 completed와 error에 대한 이벤트 처리는 불필요하다.
때문에 UI에 더 적합한 형태가 필요했고, Subject를 내부에서 Wrapping하여 Relay를 제공한다.
Realy의 종류는 PublishRealy, BehaviorRelay, ReplayRelay 3가지가 있고, subject와 거의 유사하다.
✅ Subject vs Relay
Relay는 Subject와 거의 유사한 특성을 가지고 있다.
차이점
- Subject → complete와 error이벤트를 받을 수 있다.
- Relay → next이벤트만 받을 수 있다.
Relay는 주로 UI를 구현할 때 사용한다.
UI는 error나 complete 이벤트가 발생하는 경우는 없기 때문에 next 이벤트만 있어도 된다.
이러한 이유로 Relay를 사용한다.
Relay는 next 이벤트만 처리하기 때문에 next 대신 accept 키워드를 사용한다.
💡 Disposable
Disposable은 Subscribe 중인 Stream을 원하는 시기에 정리할 수 있도록 도와준다.
dispose를 호출하지 않으면 발생하는 경고
이벤트를 구독만 하고 있기 때문에 필요하지 않을 때 Dispose를 수행하여 리소스를 정리해야 메모리 누수가 발생하지 않는다!
subscribe의 반환 값이 Disposable이다.
언젠가는 리소스가 정리되어야 한다는 의미!
때문에 dispose를 호출하지 않으면 경고 문구가 나타나는 것이다.
✅ DisposeBag
DisposeBag 클래스가 deinit이 될 때, dispose 메서드가 호출된다.
✅ Observable LifeCycle & Disposable
✔️ Observable
Observable에서 next 이벤트에 대한 emit이 끝나면 completed가 호출된 후 disposed되어 Sequence가 정상적으로 종료된다.
error 이벤트가 전달되더라도 error → disposed로 종료된다.
✔️ Subject
BehaviorSubject는 observable과 observer 역할을 모두 하기 때문에 언제 어떤 이벤트가 올지 모른다.
언제든 이벤트가 emit될 수 있는 상황이기 때문에 disposed 되지 않고, 메모리 상에 남아있게 된다.
일반적으로는 클래스 메모리가 해제되는 시점에 Disposable이 되지만, 클래스가 RootViewController일 때는 메모리에서 Disposable이 되지 않는다.
이러한 경우 직접 리소스를 관리하여 필요한 시점에 dispose 메서드 호출로 리소스를 정리해야 한다.
✅ 리소스 정리 방식
- dispose()를 직접 호출하거나나
- DisposeBag deinit을 활용하여 리소스 정리
.dispose()
즉시 리소스를 정리하여 구독을 해제한다.
때문에 한 번 수행하고 그 이후에는 실행이 되지 않는다.
화면이 나타남과 동시에 리소스 정리
주로 구독을 한 후 화면이 떠있는 동안 사용하기 때문에 더이상 필요하지 않을 때 dispose 하는 것이 바람직 함
.disposed(by: disposeBag)을 사용
'iOS > 🔎 swift 정리하기' 카테고리의 다른 글
[iOS/Kingfisher] 네트워크 통신으로 이미지 받아오기 (0) | 2023.11.26 |
---|---|
[iOS/RxSwift] CombineLatest vs Observable.zip (0) | 2023.11.19 |
[iOS/Swift] MapKit Annotation displayPriority 지정하기 (0) | 2023.10.20 |
MapKit CustomAnnotation (0) | 2023.10.10 |
[iOS/Swift] MapKit - 원하는 곳에 어노테이션을 찍어보자 (0) | 2023.10.01 |