Skip to content

Latest commit

 

History

History
190 lines (146 loc) · 5.74 KB

File metadata and controls

190 lines (146 loc) · 5.74 KB

10. Debugging

참고 문헌/웹

Combine에는 print를 이용해서 이벤트를 출력할 수 있음.

let subscription = (1...3).publisher
    .print("publisher")
    .sink { _ in }

결과

publisher: receive subscription: (1...3)
publisher: request unlimited
publisher: receive value: (1)
publisher: receive value: (2)
publisher: receive value: (3)
publisher: receive finished
  • 구독을 수신할 때 인쇄하고 업스트림 게시자에 대한 설명을 표시합니다.
  • 얼마나 많은 항목이 요청되고 있는지 볼 수 있도록 가입자의 수요 요청을 인쇄합니다.
  • 업스트림 게시자가 내보내는 모든 값을 인쇄합니다.
  • 마지막으로 완료 이벤트를 인쇄합니다.

Combine과는 별개로 print 메서드에는 to 파라미터에 TextOutputStream 타입을 전달할 수 있음.

이를 활용해 반복적인 출력을 만들어 놓을 수 있음.

class TimeLogger: TextOutputStream{
    private var previous = Date()
    private let formatter = NumberFormatter()
    
    init(){
        formatter.maximumFractionDigits = 5
        formatter.minimumFractionDigits = 5
    }
    
    func write(_ string: String) {
        let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmed.isEmpty else {return}
        let now = Date()
        print("+\\(formatter.string(for: now.timeIntervalSince(previous))!)s: \\(string)")
        previous = now
    }
}

let subscription = (1...3).publisher
    .print("publisher", to: TimeLogger())
    .sink { _ in }

출력 결과

+0.00022s: publisher: receive subscription: (1...3)
+0.01023s: publisher: request unlimited
+0.00036s: publisher: receive value: (1)
+0.00017s: publisher: receive value: (2)
+0.00016s: publisher: receive value: (3)
+0.00015s: publisher: receive finished

handleEvents

Debug에는 print를 쓰는데 RxSwift의 debug -> print, do -> HandleEvents

해당 스트림에서 다룰수 없는 이벤트(전역 변수 등 ) 예를들어 네트워크통해서 key를 받았다고 하면 sink 써서 할 수도 그 것보다는 handleEvents 를 사용함

해당 스트림이 시작할 때 무언가 처리하고 싶다면 start, 받았을 때는 receiveOutput, cancel은 receiveCancel 일때 처리를 진행

publisher의 라이프 사이클에 있는 모든 이벤트를 받을 수 있다.

publisher가 네트워크 요청을 수행한 다음 일부 데이터를 내보내야 하는 문제를 추적하고 있다고 상상해보자. 실행하면 데이터가 수신되지 않는다. what happen?

다음과 같은 코드를 생각해보자

let request = URLSession.shared
    .dataTaskPublisher(for: URL(string: "<https://www.raywenderlich.com/>")!)

request
    .sink { completion in
        print("Sink received completion: \\(completion)")
    } receiveValue: { data, _ in
        print("Sink received data: \\(data)")
    }

어떠한 이벤트도 수신이 안된다. 무슨일인지 알 수 있는 방법이 없다.

request와 sink 사이에 handleEvent 를 넣어보자

let subscription = request
    .handleEvents { _ in
        print("Network request will start")
    } receiveOutput: { _ in
        print("Network request data received")
    } receiveCancel: {
        print("Network request cancelled")
    }
    .sink { completion in
        print("Sink received completion: \\(completion)")
    } receiveValue: { data, _ in
        print("Sink received data: \\(data)")
    }

출력 결과

Network request will start
Network request cancelled

구독이 시작되지만 즉시 취소되는 중이다.

Q)Cancellable around를 유지시키지 못해서라는데 무슨말인지..?

A) 알아냈다.

참고: 모든 Cancelable은 저장해야한다. 그렇지 않으면 현재 코드 범위를 벗어날 때 deallocated 및 취소된다.

뭔 말이냐면 지금 Playground는 해당 코드를 함수에 넣어서 호출하고 있다. 함수가 종료되면서 모두 deallocated및 취소되고 있는 거임.

example("handleEvent") {
    var cancelBag = Set<AnyCancellable>()
    URLSession.shared
        .dataTaskPublisher(for: URL(string: "<https://httpbin.org/get>")!)
        .sink { completion in
            
        } receiveValue: { data, _ in
            print("\\(data)")
        }
        .store(in: &cancelBag)

    let request = URLSession.shared
        .dataTaskPublisher(for: URL(string: "<https://www.raywenderlich.com/>")!)
    
    let subscription = request
        .handleEvents { _ in
            print("Network request will start")
        } receiveOutput: { _ in
            print("Network request data received")
        } receiveCancel: {
            print("Network request cancelled")
        }
        .sink { completion in
            print("Sink received completion: \\(completion)")
        } receiveValue: { data, _ in
            print("Sink received data: \\(data)")
        }
}

이런식으로 example 함수 호출하면서 수행되고 있는 거였음.

example 함수 원문이 아래 처럼 되어 있는데 escaping은 클로저를 함수가 끝나도 잡아주는 역할을 하는데 cancel되는 거 까지는 못잡아주나봄

func example(_ title: String, completion: @escaping () -> ()){
    print("============== "+title+" ==============")
    completion()
}

image-20211231144234894

이런식으로 함수밖에다 선언하니 제대로 동작한다.

출력 결과

Network request will start
378 bytes
Network request data received
Sink received data: 307902 bytes
Sink received completion: finished