All session list link: Here
Session Link: Here
Download session slides: Here
This notes is written by Sheldon after watching WWDC18 session 412. You can find me with #iOSBySheldon in Github, Youtube, Facebook, etc.
When breakpoint hits, a tab called "Debug" will be created. // this can be set in Preferences -> Behaviors -> Pauses
Change value of any property on when debugging:
For example we have a value called didReachSelectedHeight
(lldb) expression didReachSelectedHeight = true
This could be extremely helpful if you are in the middle of debugging and realize you may miss a line of code such as:
dynamicAnimator.delegate = self
You can use expression
to add this line to your code to avoid compiling your code again.
Demo here shows some animation using UIDynamicAnimator
, worth take a look.
Next trick is to set a one-shot symbolic breakpoint. Say, you know label text should be changed after line 10 in your code. You can then put a breakpoint in line 10, and then add action:
$ breakpoint set --one-shot true --name "-[UILable setText:]"
One-shot breakpoint will be removed automatically after it is hit. Symbolic breakpoint will like make you land on the assembly debug page, in there you can type:
(lldb) po $arg1
to see if that is the label (in our example) you wanted.
Once breakpoint is hit, we can drag the burger indicator of the breakpoint to jump lines (meaning let the system skip the code we wrote for following lines). We can also do this with lldb command:
(lldb) thread jump --by 1 # jump one line
Debugging view hierarchy can be easy with the view debugging tool but we can also do it in lldb commands. The format should be something like:
(lldb) po self.view.recursiveDescription()
However, this won't work because in Swift code base, lldb closed partial debugging functions, including the one above. To use it, we need the help with objective-c
(lldb) expression -l objc -O -- [`self.view` recursiveDescription]
Here is the explanation of the above line, expression
is to run a line of code, -l
is setting the language, -O
is equal to po
, --
means no more commands, [self.view recursiveDescription]
is to loop all the subviews in self.view and show their and their subviews' description.
Note: You have to add "`" before and after self.view
because by running command this way, it will not evaluate self.view as a parameter, "`" will make it evaluate first.
The following command is pretty helpful as we explained in the above paragraph, but we can make it even easier with command alias.
(lldb) expression -l objc -O -- [`self.view` recursiveDescription]
To use command alias:
(lldb) command alias poc expression -l objc -O --
# next we can use it
(lldb) poc 0x7fb3afc3f480
# to get the info of a UIElement with its memory address
UnsafeBitCast if a function built for Swift to cast an memory address to a type, but no result is gauranteed. But it will be helpful if you know the memory address and know its type, you can use it like:
(lldb) po unsafeBitCast(0x7fb3afc3f480, ScoreboardView.self)
Say, we get one object from the unsafeBitCast, we can now play around with it and access its properties like position, center, etc. If we want to move it in the view, we can type:
(lldb) po unsafeBitCast(0x7fb3afc3f480, ScoreboardView.self).center.y = 100
But after this, nothing will be changed in the view of your simulator because the views are stored in the framebuffer. To make the view updated, we can use:
(lldb) expression CATransaction.flush()
This time, the view will be changed.
Python script file can open the full potential of all the lldb command. There are examples as a template to write the python script. But to make your lldb works with your python script, you just need to
- Open file
~/.lldbinit
- Add
command script import /path/to/your/python/file.py
to import file - Add
command alias poc expression -l objc -O --
to direct add commands
Find python script for lldb built by Apple Here
po
, p
, frame varaiable
are doing similar things but they have their differences.
po
is to print the debug description, which can be overridden by the following extension:
extension YourClass: CustomDebugStringConvertible {
var debugDescription: String {
return "<\(type(of: self) \(property1) \(property2)>"
}
}
In LLDB po <expression>
is just same as expression --object-description -- <expression>
p <expression>
in LLDB is same as just expression
, so p
will output LLDB-formatted description.
In case of po
& p
both not working, we can also try frame variable <name>
, LLDB will read the values of <name>
from memory and output LLDB-formatted description