Combine Debugging

sanghee·2022년 5월 2일
0

🍀인턴 스터디

목록 보기
12/12

Combine Debugging🐞

Combine을 이용해서 디버깅하는 방법으로는 다음과 같다.



1. 출력하기

  • 모든 publisher 이벤트들을 위한 로그 메세지들을 출력한다.

코드 예시

  • 메인뷰컨트롤러에서 bindViewModel의 코드를 예시로 살펴보자.
  • publisher를 통해 어떤 값을 전달받는지 확인한다.
func bindMainViewModel() {
    mainViewModel.cameraUpdate
        .receive(on: DispatchQueue.main)
        .print("cameraUpdate")
        .sink(receiveValue: { [weak self] cameraUpdate in
            ...
        }).store(in: &cancellables)

출력 결과

cameraUpdate: receive subscription: (ReceiveOn) // 구독함
cameraUpdate: request unlimited // publisher가 생성하는 값들을 제한없이 요청
cameraUpdate: receive value: (nil) // 초기값
cameraUpdate: receive value: (Optional(<NMFParamUpdate: 0x280faf020>)) // 값 업데이트됨

시간 표시하기

  • 이전 이벤트와의 시간 간격을 출력하기 위한 클래스이다.
  • TextOutputStream 프로토콜을 준수해야 한다.
    • write 메서드를 구현해야 한다.
    • 내부에 print함수가 있어야 출력된다.
final class TimeIntervalLogger: TextOutputStream {

    private let formatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.maximumFractionDigits = 5
        formatter.minimumFractionDigits = 5
        return formatter
    }()
    private var previous = Date()

    func write(_ string: String) {
        guard !string.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return }
        let now = Date()
        guard let timeInterval = formatter.string(for: now.timeIntervalSince(previous)) else { return }
        previous = now
        print("\(timeInterval)s \(string)")
    }

}
func bindMainViewModel() {
    mainViewModel.cameraUpdate
        .print("cameraUpdate", to: TimeIntervalLogger())
        .sink(receiveValue: { [weak self] cameraUpdate in
            ...
        }).store(in: &cancellables)
  • 이전 이벤트와의 시간 간격이 앞에 출력되는 걸 확인할 수 있다.
0.00036s cameraUpdate: receive subscription: (ReceiveOn)
0.00009s cameraUpdate: request unlimited
0.17119s cameraUpdate: receive value: (nil)



2. 특정 사건 처리

  • 각 단계들에서 처리해야 할 코드들을 작성할 수 있다.
  • 예시에서는 단순하게 출력만 해본다.
func bindMainViewModel() {
    mainViewModel.cameraUpdate
        .print("cameraUpdate", to: TimeIntervalLogger())
        .handleEvents(receiveSubscription: { _ in print("구독 받음") },
                      receiveOutput: { _ in print("구독 결과") },
                      receiveCompletion: { _ in print("구독되거나 오류로 종료됨") },
                      receiveCancel: { print("구독 취소") },
                      receiveRequest: { _ in print("구독 추가 요청") })
  • 구독의 각 단계들을 출력해볼 수 있다.
구독 받음
구독 요청
cameraUpdate: request unlimited

cameraUpdate: receive value: (nil)
구독 결과

cameraUpdate: receive value: (Optional(<NMFParamUpdate: 0x280eba580>))
구독 결과
  • 만약 *cancellables를 저장하지 않았다면 구독을 요청해도 바로 취소된다.
0.00039s cameraUpdate: receive subscription: (ReceiveOn)
구독 받음
구독 추가 요청
0.00010s cameraUpdate: request unlimited
구독 취소
0.00007s cameraUpdate: receive cancel

*Cancellable

  • 모든 Cancellable은 저장해야 한다.
  • 그렇지 않으면 구독은 시작되지만 코드 범위를 벗어날 때 즉시 취소된다.



3. Debugger 사용

3-1. breakpointOnError()

  • publisher에서 오류가 발생하면 break된다.
  • 내부의 조건(value == nil)일 때 중단된다.
func bindMainViewModel() {
        mainViewModel.cameraUpdate
            .breakpointOnError()
            .breakpoint( receiveOutput: { value in
                return value == nil
            })



**참고문서**

profile
👩‍💻

0개의 댓글