Advanced Debugging Tips and Tricks:
- Injecting Code at runtime
We can change values of variables at runtime while debugging (here variable_name is a Bool)
expression variable_name = false
Here we are injecting value at runtime, so no need to run again to see the effect. (Other eg., expression animator.delegate = self) - Under Xcode > Preferences > Behaviours > Running > Pauses > Check Show Tab Named, In order to show new tab while a breakpoint is hit. We can set other behaviours as well.
- We can add symbolic breakpoints on methods in frameworks. like
This is in objective c because UIKit is in objective c. - In order to find the values/parameter of a function inside framework, we can use
For expression -[UILabel setText:]
po $arg1
<UILabel ****>
po (SEL)$arg2
"setText:"
po $arg3
"0 ft" - We can set symbolic breakpoints in 2 ways
1. By clicking plus in bottom left and choosing symbolic (Cons: Sets BP in all places)
2. By adding a breakpoint > Editing it to specify a debugger command. (Pros: we can set at a desired method, for eg., after completion of some task)
- Skipping code execution after compilation.
for example if i want to skip line 10 in editor and continue execution at line after line 12. There are 2 ways.
1. Keep BreakPoint at line 10 and Drag the Thread (Instruction Pointer) to desired line 12.
2. Add breakpoint at line 10 with debugger command "thread jump --by 2"
Use Case:
Jump execution of a function at line 10 and execute the same function with different parameters - Use CustomDebugStringConvertible protocol to add our own format of debug description by implementing debugDescription property and returning desired format.
- po is programatic description of object. p is description of format specified by LLDB.
- watchpoint watchpoint for a variable means, a breakpoint is set for a variable and it is called/execution paused when the value is changed next time.
- To execute swift code in objc in LLDB
Swift code: self.view.recursiveDescription()
The above code throws error as the function is not strictly defined. so we run same code in objc as it is dynamic language.
For Objc way:
expression -l objc -O -- [`self.view` recursiveDescription]
objc = to tell we are giving objc code even though we are in swift lldb frame
-O = to give debug description
-- = to tell no more options
`` = are to inherit variable from swift frame to objc - Creating shortcuts for lengthy commands.
command alias ALIAS_NAME expression -l objc -O --
The above command creates shortcut, so next time.
ALIAS_NAME [`self.view` recursiveDescription] - Printing variable from memory address 2 ways.
1. po 7x99890s0s
2. po unsafeBitCast(7x99890s0s, to: CustomViewType.self)
unsafeBitCast is more useful as you can print property names and functions on it, like
po unsafeBitCast(7x99890s0s, to: CustomViewType.self).frame - Assigning/Modifying view properties from LLDB
po unsafeBitCast(7x99890s0s, to: CustomViewType.self).center.y = 100
This gets updated only after "expression CATransaction.flush()" (as we are paused in debugger to run po command, this command tell core animation to update ui)
- To click through the view hold command while click.
For eg., to select a view which is beneath other full screen view. - Windows are shown as multiple root level objects on left hand side of view hierarchy.
- e is shortcut for expression.
- we can create backtraces for views in views hierarchy, by settings.
Scheme > Edit Scheme > Diagnostics > Logging > Check - Malloc Stack > Select - All allocations and free history
Try:
po classification
Creates new simpler context with frame of variables so that we can inspect variable values.
po variable_name
prints : "Mercury"
po frame variable variable_name
prints : "(String) variable_name = Mercury"
Comments
Post a Comment