디버깅의 가장 기본적인 방법은 print문을 사용하는 것입니다. Combine에서도 마찬가지로 publisher에 일어나는 모든 일을 콘솔에 출력해주는 메소드인 print가 존재합니다.
let publisher = (1...20).publisher
let subscription = publisher
.print("디버그")
.sink(receiveCompletion: { _ in },
receiveValue: { _ in })
//🖨 출력 결과
디버그: receive subscription: (1...20)
디버그: request unlimited
디버그: receive value: (1)
디버그: receive value: (2)
디버그: receive value: (3)
디버그: receive value: (4)
디버그: receive value: (5)
디버그: receive value: (6)
디버그: receive value: (7)
디버그: receive value: (8)
디버그: receive value: (9)
디버그: receive value: (10)
디버그: receive value: (11)
디버그: receive value: (12)
디버그: receive value: (13)
디버그: receive value: (14)
디버그: receive value: (15)
디버그: receive value: (16)
디버그: receive value: (17)
디버그: receive value: (18)
디버그: receive value: (19)
디버그: receive value: (20)
디버그: receive finished
print는 publisher에 관련된 모든 이벤트를 출력합니다. 따라서 원하는 디버깅 포인트를 잡기 어려울 수도 있습니다. 이 경우에는 handleEvent를 사용하면 됩니다. subscription, output, completion, cancel, request 마다 원하는 메소드를 실행할 수 있습니다.
let publisher = (1...20).publisher
let subscription = publisher
.handleEvents(receiveSubscription: { _ in print("Subscribed") },
receiveOutput: { _ in print("Received")},
receiveCompletion: { _ in print("Completed") },
receiveCancel: { print("Canceled") },
receiveRequest: {_ in print("Requested") })
.sink(receiveCompletion: { _ in },
receiveValue: { _ in })
//🖨 출력 결과
Subscribed
Requested
Received
Received
Received
Received
Received
Received
Received
Received
Received
Received
Received
Received
Received
Received
Received
Received
Received
Received
Received
Received
Completed
print와 더불어 디버깅에 가장 많이 사용하는 breakpoint입니다. 클로저가 true를 리턴하면 해당 시점에 자동으로 breakpoint를 잡아줍니다. subscription, output, completion에 사용할 수 있고 에러가 발행되면 실행되도록 할 수도 있습니다.
let publisher = (1...20).publisher
let subscription = publisher
.breakpoint(receiveSubscription: { _ in true })
.breakpoint(receiveOutput: { $0 > 10 })
.breakpoint(receiveCompletion: { _ in true })
.breakpointOnError()
.sink { print($0) }