- RxSwift 6.6.0
기준으로 작성된 글입니다.
RxSwift 구현을 살펴보던 도중 이해하기 힘들었던 로직에대한 기록.
문제:
/**
Subscribes `observer` to receive events for this sequence.
- returns: Subscription for `observer` that can be used to cancel production of sequence elements and free resources.
*/
public func subscribe(_ observer: @escaping (SingleEvent<Element>) -> Void) -> Disposable {
var stopped = false
return self.primitiveSequence.asObservable().subscribe { event in
if stopped { return }
stopped = true
switch event {
case .next(let element):
observer(.success(element))
case .error(let error):
observer(.failure(error))
case .completed:
rxFatalErrorInDebug("Singles can't emit a completion event")
}
}
}
그림 1. `PrimitiveSequenceType` 의 인스턴스 함수 구현(예시는 SingleTrait)
그림 1의 구현에서 `stopped` 변수가 하는 역할이 무엇인지 이해가 되지 않았음.
Goal:
- `stopped` 변수의 역할 이해
- 전체 로직의 이해
이해를 위한 기반 지식: Closure 의 캡쳐 방식(Reference / Value). https://babbab2.tistory.com/83 블로그에 정리된 내용이 도움이 됐습니다.
삽질 과정:
- 코드 흐름을 따라가며 `stopped` 변수의 역할을 유추해봄 -> 클로저 내부에서 외부 변수 값을 변경하는게 무슨 의미를 가지는지 잘 모르겠음
- chatGPT 에 문제의 코드를 그대로 복사해서 `stopped` 변수의 역할을 물어보니 중복 호출을 방지하기 위함이라고 답변 -> chatGPT 가 답변한 중복 호출의 정의가 무엇인지, 어떻게 중복 호출이 방지되는지 모르겠음
- Playground 에서 직접 비슷한 코드를 짜보며 여러 케이스를 테스트 -> 문제 해결!
Resolve:
func bar(_ closure: @escaping (() -> Void)) {
closure()
closure()
}
func foo() {
let id: UUID = .init()
var stopped = false
bar() { // 해당 클로저가 어디선가 여러 번 호출되어도 클로저 내의 코드가 한 번만 실행되도록 보장.
if stopped { return }
stopped = true
print(id)
print(stopped)
print("Do something!")
}
return
}
foo() // 호출 1
foo() // 호출 2
// 출력:
//
// AEB13E8B-98C5-4BB5-929D-1A25736D1485
// true
// Do something!
// 7652AD6F-C2A4-4627-A433-67CD11E6F76D
// true
// Do something!
그림 2. 상황을 재현하기 위한 간소화 코드
클로저를 정의할때는 해당 클로저가 한 번만 실행될 것이라고 예상할 수 있지만 실제로 클로저가 어디서 어떻게 몇 번 호출될 것인지는 미지수. 하지만 그림 1, 2 처럼 특정 flag 변수를 이용한다면 Reference capture 를 이용해 클로저 내부의 코드가 한 번만 실행되도록 보장할 수 있음.
결론
- 그림1의 구현에서 `stopped` 변수가 하는 역할: 클로저 내부의 코드가 한 번만 실행되도록 보장(아마도 중복 호출로 인한 중복 요소 방출을 막기 위함)
- Closure 사용에 있어서 캡쳐에 대한 지식이 부족해서 로직 이해가 힘들었음.
- Closure 내부의 로직을 한 번만 실행되도록 보장하기 위해서 사용할 수 있는 테크닉?을 습득.
'Computer' 카테고리의 다른 글
Class vs Struct 성능 비교 테스트 (4) | 2024.03.14 |
---|---|
[RealmSwift] Index 사용에 대한 성능 테스트 기록 (0) | 2024.02.20 |
RxSwift 구현에 대한 이해 기초 (1) (1) | 2024.02.15 |
[RxSwift] `UITextField.rx.text` 프로퍼티의 '예상치 못한 요소 방출' 이슈 (0) | 2024.02.14 |
Test Double 특징 (0) | 2023.08.18 |