iOS, Objective-C, Swift, Design and Whatever Comes in Mind
‹ Back to the Blog

Advanced Debugging with Xcode and LLDB – Sharing my Notes

I watched the WWDC talk and I would like to share my notes with you. You can find the recording as well as the mentioned script over here.

  • Xcode debug tab can be opened when a breaktpoint is hit via settings > Running > Pauses > check “Show tab named: Debug”
  • po <variable> to get the value of a variable
  • expression <expression> (eg. expression didReachSelectedHeight = true) to execute code at the breaktpoint, useful to always take one branch of an if-else-statement
  • Breakpoints can execute a LLDB command and then continue running. When double-clicked, one can enter the command via “Add Action”. Enabling “Automatically continue after Evaluation” tells the debugger to execute the command and continue to run the program. Combined with the aforementioned point it is possible to (always) take one branch of an if-else-statement whilst debugging.
  • Shortcut the "change>compile>run" workflow by injecting the change directly through LLDB to your running code. Just add another breakpoint and add the code you just inserted to your source file here, too. expression <code you just updated> does the trick that helps to tighten the workflow.
  • Debug navigator > add symbol > "add symbolic breakpoint" to add breakpoints to framework's code. For example [UILabel setText:] to add a breakpoint that hits every time a labels text is changed. Resolving the methods name succeeded when a text like “in UIKitCore” appears beside your new breakpoint. When this breakpoint hits, one can
    • po $arg1 to print the receiver of the Objective-C message (the UILabel in this case).
    • po (SEL)$arg2 to print the selector that is sent to the object.
    • po $arg3 to print the first argument passed into the method.
  • In a breakpoint, another breakpoint can be set dynamically with breakpoint set --one-shot true -name [UILabel setText:] (one shot breakpoint: only exists until it is triggered and then removed). Useful to “enable” a breakpoint only after a given part of code is executed, for example when the text of a label is updated in the following code.
  • Change the instruction pointer while the execution is paused by grabbing the grab-handle left besides “Thread 1: breakpoint…” in the green bar.
  • thread jump --by 1 tells the debugger to jump one code line ahead when the breakpoint is hit. Useful to skip code or execute different code by adding another action to the breakpoint.
  • Adding a breakpoint to a variable declaration will pause execution every time the variable is accessed.
  • po <variable> uses the debugDescription method of an object, p <variable> is more verbose in some cases.
  • Watchpoints pause the execution every time the value of a variable is changed. They can be added by right-clicking on the variable in the left side of the debugger pane. They appear below regular breakpoints in Xcode's navigator.
  • expression -l objc -O -- [’self.view' recursiveDescription] will print the description of the view as well as all contained subviews. It is an internal Objective-C method and can not be called using Swift. “’“ around self.view will tell the debugger to evaluate this expression first.
  • Printing the content of memory addresses like po 0x67aef7891 will not work using swift. One must use expression -l objc -O -- po 0x67aef7891​. A handy way to create a shortcut is by typing command alias poc expression -l objc -O --. Now it is possible to type poc 0x67aef7891.
  • In Swift, you can also use po unsafeBitcast(0x2d34bd25, to: YourView.self) instead of using Objective-C evaluation. You can even chain expressions together, like po unsafeBitcast(0x2d34bd25, to: YourView.self).center.y = 300. When a UIView property is changed in this way, one need to tell CoreAnimation to update its frame buffer, as the execution is currently paused: expression CATransaction.flush()
  • A python script that changes properties of the view using the debugger is presented. To use commands provided by this script, open ~/.lldbinit in you home directory and add command script import ~/nudge.py. You can also define your previously created aliases there.
  • Using the nudge tool, one can live update positions of views by using the debugger.

"Advanced Debugging with Xcode and LLDB – Sharing my Notes".