정말 생초보,, 아무것도 모르는 입장에서 강의 영상을 보고 의식의 흐름대로 작성한 글이니 비판의 눈으로 글을 읽어 주시면 감사하겠습니다~~ 오류 지적 대환영!
Observable Life-Cycle
1. Create
Observable
생성- 데이터가 생성되거나, 어떤 명령이 동작하지 않음 → 2.
Subscribe
에서 동작!
2. Subscribe
- 어떠한
Observable
이 동작함
3. Next
- 데이터 전달
4. Completed
- 정상적으로 동작 끝
4-1. Error
- 비정상적으로 동작 끝
5. Disposed
Dispose
되면 그Observable
은 더 이상 재사용 불가
.debug()
로 Observable 상태 확인 가능
순환 참조와 메모리 관리
.subscribe(onNext: { i in
self.countLabel.text = "\(i)"
})
.disposed(by: disposeBag)
이 코드에서 subscribe
내에서 UI 작업을 하느라 self
(ViewController)를 참조. 이미 VC 인스턴스를 생성하면서 한 번 참조된 것임. VC가 pop 되더라도 위 클로저에서 한 번 참조된 게 남아 있음! (4번의 RC=1) 이 VC 인스턴스는 더 이상 안 쓰는데...→ 순환 참조에 의한 메모리 누수(Memory Leak)
메모리 누수를 해결하려면 약한 참조(weak self
)를 사용하거나, onCompleted()
를 통해 Subscribe
클로저 자체를 종료시킨다.
- 약한 참조(weak self)
.subscribe(onNext: { [weak self] i in
self.countLabel.text = "\(i)"
})
.disposed(by: disposeBag)
weak self
를 안 썼을 때는 자동으로 강한 참조(strong)로 사용됨. weak self
는 위의 코드와 같이 사용하며, 참조될 때 RC를 증가시키지 않는다! 상위 인스턴스가 해제되면(RC- -) 얘는 바로 메모리에서 날아감(RC=0).
subscribe
의 클로저를 종료시키는 또 다른 방법:Observable
을 만들 때onCompleted()
명시
emitter.onNext(image)
emitter.onCompleted()
return Disposables.create()
뭐 이런 식으로... onCompleted
가 꼭 실행되도록 명시하면 Observable
동작 자체가 종료되면서 메모리가 해제됨.
스레드 분기
DispatchQueue
,OperationQueue
를 사용하는 대신observeOn
,subscribeOn
을 사용함! (DispatchQueue
,OperationQueue
를observeOn
,subscribeOn
가 감싼(wrapping) 개념)
subscribeOn
- 한 번만 사용 가능, 구독 시 시작할 스레드 지정
- subscribeOn이 지정된 위치에 상관없이 첫 스레드를 지정함!
- 위에 있는 Stream에 영향을 줌 → 업스트림(Up Stream)
observeOn
- 여러 번 사용 가능, observeOn에서 스레드를 지정한 후 그 아래부터의 Stream에 작동 → 다운스트림(Down Stream)
Stream의 분리 및 병합
merge
- Observable 2개를 1개로 merge
- 하나로 합쳐야 하기 때문에 데이터 타입을 통일해야 함!
zip
- 쌍으로 만들어 전달 → 데이터 타입 달라도 상관 X
1----2--------3---------4---->
B----------C---A------------->
########### zip ############
1B---------2C--3A------------>
- 데이터의 개수는 가장 작은 스트림의 데이터 개수와 동일!
combineLatest
- zip과의 차이점: 가장 최근의 데이터와 쌍을 이뤄 전달
1----2--------3---------4---->
B----------C---A------------->
######### combineLatest #########
1B---2B----C2-3C--A3----4A--->