Xcode and LLDB Advanced Debugging Tutorial: Part 2
In the first part of this three parts tutorial, we’ve covered how to utilize Xcode breakpoints to manipulate an existing property value and inject a new line of code via expression statements.
I developed a demo project with several intentional bugs to elaborate on how to use different types of breakpoints alongside the LLDB to fix bugs in your project/application.
If you didn’t go through part 1 of this tutorial, it’s crucial to check it before proceeding with this part.
Let me remind you of the golden rule of this tutorial:
You’re not to stop the compiler or re-run the application after running it for the very first time. You’re fixing the bugs at runtime.
Watchpoints 👀
Let’s march to our next enemy.
3. The user is allowed to load posts more than 7 times.
Here are the steps to reproduce this one:
✦ Turn your iPhone’s/Simulator’s internet connection on.
✦ Scroll to the bottom of the table view to load more posts.
✦ Scrolling/loading more posts is valid for more than 7 times. (Bear in mind that for the current application, the user is only allowed to load posts for 7 times only)
One approach to consider this bug is to figure out how the pageNumber
integer property is being updated since it’s passed to the networking manager to retrieve new posts objects for a specific page. In a code base that you’re still unaware of, it would take you some time and effort to figure out where exactly this is happening.
Worry not! Let’s do some magic 🎩
From part 1 of this tutorial, you learned that the GET HTTP request is executed in the section with the pragma mark Networking
. It only includes one function which is loadPosts
. Place a breakpoint on the first line of this function and pull down to refresh to reload new posts objects. This will trigger the breakpoint you’ve just added.
In the bottom debugger window, tap on the “Show variables view button”. This will slide a new view that includes all of the properties for PostsTableViewController.
Head to the pageNumber
property, right-click, and select “Watch _pageNumber” / “Watch pageNumber”.
That resulted in creating what is so-called a “Watchpoint” to the pageNumber
property. A watchpoint is a type of breakpoint that pauses the debugger the next time the value of the property it’s set to get changed.
Continue the program execution. The debugger will pause and you’ll see something like this:
Objective-C
- Logs of the old and new values of the
pageNumber
property. - The stack trace of the code that resulted in the change of the
pageNumber
property. - The current point that is causing the actual change of the
pageNumber
property. That is the setter method of the property.
If you fall back to point 1 in the stack trace, it will lead you to the following piece of code:
Swift
- Debugger console informing you that the watchpoint you did set got hit.
- The stack trace of the code that resulted in the change of the
pageNumber
property. - The current point that is causing the actual change of the
pageNumber
property. That is theupdateForNetworkCallEnd
function.
It’s obvious to conclude that for every time the HTTP GET request succeeds, the pageNumber
property will increment by 1 as long as the state
enum property is active. The state
enum property can be one of two values either “active” or “inactive”. An active state refers that the user is able to load more posts (i.e didn’t reach the load limit [7]). The inactive state is the mere opposite to that. In conclusion, we need to implement some logic inside the updateForNetworkCallEnd
that checks on the pageNumber
property and sets the state
enum property accordingly.
As you’ve learned, it’s quite better to test the hypothesis first and then make actual changes to your code without stopping the compiler.
You’ve guessed it right 😉
It’s important to note that there’s an already implemented function under the section with the pragma mark Support
that does set the state
enum property to inactive. That is setToInactiveState
.
Add a breakpoint one line above the if condition. Add a debugger command action. Add the following debugger command.
Objective-C
expression if (self.pageNumber >= 7) {[self setToInactiveState]}
Swift
expression if (self.pageNumber >= 7) {setToInactiveState()}
After doing that, you need to deactivate the very first breakpoint you did utilize to set the watchpoint. Disable the watchpoint as well.
Now get back to the top of the table view, pull down to refresh, and then start scrolling down.
Don’t party yet, we still have one more bug to kill 😄⚔️
Where to go?
Check out the third and final part of this tutorial to fix the last bug and learn about a new type of breakpoints that is symbolic breakpoints.