Combine debugging using operators in Swift – onlinecode
In this post we will give you information about Combine debugging using operators in Swift – onlinecode. Hear we will give you detail about Combine debugging using operators in Swift – onlinecodeAnd how to use it also give you demo for it if it is necessary.
Combine debugging can be hard with long stack traces which don’t help at all. Asynchronous callbacks follow up on each other rapidly and easily make it hard to find the root cause of an issue. It’s next to the big learning curve one of the most common reasons to not go for reactive programming in projects.
Luckily enough there are a few tips and tricks to improve the debugging experience in Xcode. Apple even introduces specific debugging operators for you to use!
Just getting started with Combine? You might want to first take a look at Getting started with the Combine framework in Swift or my Combine Playground.
Debugging using the handleEvents operator
The handleEvents operator allows you to catch any events on a publisher. It will perform the specified closures whenever the related event occurs.
let subject =PassthroughSubject<String,Never>()let subscription = subject.handleEvents(receiveSubscription:{(subscription)inprint("Receive subscription")}, receiveOutput:{ output inprint("Received output: (output)")}, receiveCompletion:{_inprint("Receive completion")}, receiveCancel:{print("Receive cancel")}, receiveRequest:{ demand inprint("Receive request: (demand)")}).sink {_in}
subject.send("Hello!")
subscription.cancel()// Prints out:// Receive request: unlimited// Receive subscription// Received output: Hello!// Receive cancel
It allows you to define closures for:
- Receiving a new subscription. The closure parameter points to the new subscription.
- New received values. The closure parameter contains the value.
- The completion event including the type of completion: failure or success. Will not be called when the subscription is canceled.
- The cancelation event which will not be called if the subscription is already completed.
- Receiving a request for more elements. The closure includes the demand value which will either be unlimited or a defined maximum number of items.
All closures are optional and therefore allow you to listen to only one of them if needed.
In the above code example prints are being used to help to debug. Obviously, you can also use breakpoints inside the closure to use LLDB to debug even deeper.
Debugging a Combine stream using prints
The print operator logs messages for all publishing events and helps to get more insights into changes of a stream.
let printSubscription = subject.print("Print example").sink {_in}
subject.send("Hello!")
printSubscription.cancel()// Prints out:// Print example: receive subscription: (PassthroughSubject)// Print example: request unlimited// Print example: receive value: (Hello!)// Print example: receive cancel
As you can see, it almost prints out the same as our previous code example using the handle events operator. The print operator, however, is a lot easier to use and allows you to pass in a prefix like “Print example” as we used here.
It’s perfect when you quickly want to print out some more information but it does not allow you to debug using breakpoints.
Using the breakpointOnError operator
The breakpointOnError operator does exactly what you expect: trigger a breakpoint when an error occurs inside a publisher. The operator raises a SIGTRAP signal which will stop the process in the debugger. Do note that it might not stop in the right thread and position in the stack trace. Therefore, you might need to navigate a bit to find the stream that failed.
If you’re done debugging you can simply press continue and your process will continue as normal.
Triggering a Combine debugging breakpoint based on state
The breakpoint operator allows you to trigger the same signal as the breakpointOnError operator based on a specific state. It comes with optional closures to trigger a breakpoint when a new subscription, a new value or a completion event is received.
URLSession.shared.dataTaskPublisher(for: url).map{ $.data }.decode(type:SearchResponse.self, decoder:self.decoder).map{ $.items }.breakpoint(receiveOutput:{(items)->Boolin// Only trigger a breakpoint when the items count is 1return items.count==1}).catch{ error ->Just<[Repo]>inprint("Decoding failed with error: (error)")returnJust([])}
A breakpoint will only be triggered if one of those closures is implemented and returns true
. Therefore, an empty breakpoint()
operator will do nothing more than passing through the values.
Up until Xcode 11 beta 3, this operator does nothing more than triggering a breakpoint. The stack trace you get provides useless information and does not even allow you to navigate to the causing operator. If anything changes in this behavior, this blog post will be updated.
Swift Playground
Everything described in this blog post is added as a separated page to my Swift Combine Playground which you can find here.
Conclusion
After the big learning curve that comes with Reactive Programming, debugging is stated as one of the many reasons to not go with a framework like Combine. Hopefully, this blog post takes away the debugging troubles you might foresee. However, it’s still a lot harder to debug reactive code compared to non-reactive code.
Therefore, try to keep your implementations to the minimum and only use reactive programming solutions if they really make sense.
To read more about Swift Combine, take a look at my other Combine blog posts:
- @Published risks and usage explained with code examples
- RunLoop.main vs DispatchQueue.main: The differences explained
- PassthroughSubject vs. CurrentValueSubject explained
- How to observe NSManagedObject changes in Core Data using Combine
- Getting started with the Combine framework in Swift
- Error handling in Combine explained with code examples
- Combine debugging using operators in Swift
- Creating a custom Combine Publisher to extend UIKit
<!– Disable cross link to Medium
Also published on Medium.
–>
Hope this code and post will helped you for implement Combine debugging using operators in Swift – onlinecode. if you need any help or any feedback give it in comment section or you have good idea about this post you can give it comment section. Your comment will help us for help you more and improve us. we will give you this type of more interesting post in featured also so, For more interesting post and code Keep reading our blogs