Are you frustrated with having to re-run every time you fix a Bug to verify the results? Are you struggling with UI modifications where WYSIWYG is what you see? Do you have to wait several times for a recompile to run because you have to fix a small problem? Now, by studying this article, you can not only solve your problems, but also improve your debugging ability so that you are not limited to printing variable values using p/ Po only with breakpoints.
The following is the main content of this article:
- Modify simple logic-expression
- Skip unwanted statements – Thread jump
- Modify the UI – recursiveDescription with Debug
Without further ado, let’s get started!
The use of the expression
In our daily development, we often run into bugs in certain situations, such as the following code:
// Bug: subtract operation error, should subtract oneif isAdd {
count = count + 1
} else {
count = count - 2
}
countLabel.text = "\(count)"
Copy the code
Code description:
IsAdd is a Boolean that we use to operate on count. The normal requirement is: if isAdd istrueWe increment count by one; If isAdd isfalseWe subtract one from count.Copy the code
Now depending on the context isAdd is true, if we were to test for false, we might manually set isAdd to false in the project and rerun the project to verify the changes. So how do we change the value of isAdd without having to rerun the project? The answer is expression.
Expression can be used in two ways:
- Enter in LLDB: Enter every time
- Configure at breakpoint: Enter only once
Used in LLDB
Configuration in breakpoints
The following is the specific operation process:
- in
if isAdd {
Break this line of code - Right click breakpoint selection
edit Breakpoint
- Click the Action button in the pop-up box and enter in the text box below
expression isAdd = false
- Select the Optional option
If the statement executes an else branch, you can also set count = count-1 as an expression to verify the result.
Plus: The edited breakpoint adds a white triangle inside the arrow, showing the difference between the two figures above. This will make it easier to find the edited breakpoints.
Use thread Jump
We can use this command when we want to skip a line of code, and when we do, Xcode will pop up a warning telling us that this is dangerous. So, when we use it, we want to make sure that there are no problems before we use it.
The details are similar to the previous steps, except that the command is replaced with Thread jump –by 1. The value of 1 in this command means that line 1 is skipped, and we can change this value to suit our needs.
Modify the UI
Here is a very useful command that uses breakpoints to debug UI problems. In daily development, we often fine-tune some UI styles, and it is very time-consuming to recompile and run every time we change it. We can use LLDB to realize the effect without running.
For example, if we want to change the position of a child control of self.view, we can print the details of all child controls of self.view using the following command.
// Format: expression-lObjc -o -- <expr> // - Prints self. View subview expression-l objc -O -- [`self.view` recursiveDescription]
Copy the code
We can use the following command to get the memory address of the control to be changed, and then use the following command to change the frame of the child control:
// unsafeBitCast(point, to:type// The first argument is the memory address of the child control, and the second argument is the type of the child control. Expression unsafeBitCast(0x7FA94CB015c0, to: uibutton.self).frame.origine.x = 100Copy the code
After changing the memory address of the child control, we can use the following command to refresh the staging area and see the actual effect instead of re-running it.
// Flush the deferred expression catransaction.flush ()Copy the code
Note – Sets the alias
The command above is long and cumbersome to type every time, we can also set aliases to use it.
// Set the alias commendaliasAlias the original command // to use flush instead of expression catransaction.flush ()command alias flush expression -l objc -- (void)[CATransaction flush]
Copy the code
p po frame
P/Po: No substantial difference, depending on the format you need to use. Frame: The LLDB format is directly obtained from the memory.Copy the code
- Frame should work when P/Po is unavailable
- In Xcode10.2, v/vo has been added to replace p/ Po. See here for details
conclusion
- LLDB expressions can modify the state of code
- through
thread jump --by 1
Skip the code - Use obJ-C code in the Swift framework:
expression -l objc -O -- <expr>
- Refresh the view staging area:
CATransaction.flush()
- Set alias:
command alias poc expression -l objc -O --
command alias flush expression -l objc -- (void)[CATransaction flush]
Copy the code
reference
- Advanced Debugging with Xcode and LLDB