While LLDB commands are nice, helpers in Swift are way more convenient, easier to write, test and maintain.
This project has been heavily inspired by @kastiglione. You should check out his talk.
- Clone this repo
- Open the
LLDOSwiftHelper.xcodeproj
Xcode project. - Run in the Simulator and wait to hit the breakpoint in
AppDelegate.applicationDidBecomeActive
. - Start messing around. For example:
# Highlights
po UIView.current.highlightLayoutMargins(depth: 2)
po UIView.current.highlightLayoutMargins(false, depth: .max)
# Poking around
po UIButton.first()
po UIView.current.all(UILabel.self)
po UIView.grep("Pass")
po UIView.find(byAccessibilityID: "username_input")
po UIView.current.tree().filter { $0.isHidden }
# Changing stuff
po UITextField.first()?.enterText("mail@company.com")
po UISwitch.first()?.slide()
po UIButton.first()?.tap()
# Automation
load_actions lldb_actions/
login
# For the rest we need additional LLDO's LLDB commands
# Hint: You can use drag and drop the path from Finder 📎
command script import </path/to>/LLDO
# Load a reference design to check for abberations
proofimage </path/to>/LLDO/LLDOSwiftHelper/demo_reference.png
po UIImageView.at(<memory address>).removeFromSuperview()
# OR
po UIView.root.overlay()
Add the following line to your ~/.lldbinit
:
command script import /path/to/LLDO
This loads LLDO's LLDB commands by default and makes them available in every project. Whenever you are in LLDB you can type lldo
to load the Swift helper methods.
If you want to always have them available, create a symbolic breakpoint in UIApplicationMain
, enter lldo
as Debugger Command and check the Automatically continue checkbox. You might even right click that breakpoint and move it to your user so it's automatically available in all your projects.
To be able to use the Swift helpers in an Objective-C only project on a device, you need to bundle the necessary Swift runtime libraries:
- Add a single Swift file
- Do not create a bridging header
- make sure you
import UIKit
See (lldb) help load_swift_runtime
for details.
The documentation of the Swift helpers lives at lurado.github.io/LLDO.
Alias | Description |
---|---|
ps |
Like po but always use Swift. Very handy when using the Swift helpers in an Objective-C context. |
alias |
Create a LLDB command alias: alias <name> <command> . |
history |
Shows the LLDB command history. Like the Bash command. |
import |
Load a Python script: import </path/to/script.py> . |
shell |
Execute a shell command, e.g. shell ls -la . |
reload_lldbinit |
What it says on the tin. Very handy when developing commands. |
Command | Description |
---|---|
lldo |
Load the Swift helpers. |
load_swift |
Load a Swift source code file: load_swift <path> |
load_swift_runtime |
Load the Swift runtime. Necessary in Objective-C only projects. |
load_actions |
Loads LLDB scripts from a folder: load_actions <path> |
load_image |
Creates a UIImage from a file on your local hard drive: load_image </path/to/image> |
proofimage |
Displays an image from your local hard drive as semi-transparent fullscreen overlay to compare your layout with a reference design: proofimage </path/to/image> |
psource_folder |
Prints the source folder path of the current breakpoint. |
Use the built in help
command for further details, e.g. (lldb) help load_image
.
The Swift Helpers and LLDB commands can be combined into little, powerful scripts to automate tasks you do repeatedly. For example you can create UI automations to, say, log you in or bring your app into a specific state.
To create a script just put a sequence of LLDB commands in a .lldb
file and call load_actions <path>
with the folder path containing the file.
load_actions
will automatically load all .lldb
files in that folder and create actions base on their filenames:
A login.lldb
will result in a login
action.
The <path>
parameter for load_actions
may be relative.
However, in order for that to work, the breakpoint at which the application is stopped must be in the application source.
Just hitting the pause icon and trying to use a relative path won't work.
If you want to share actions with your team and always have them available, you need to create a shared symbolic breakpoint in your application that loads the actions with a relative path:
- Create a symbolic breakpoint
- For Swift projects:
- Symbol:
@objc <module>.<AppDelegate>.init
, e.g. (@objc LLDO.AppDelegate.init
)
- Symbol:
- For Objective-C projects:
- Symbol:
main
- Module:
<module>
, e.g. (LLDO
)
- Symbol:
- For Swift projects:
- Add a Debugger Command action:
load_actions <relative/path>
, e.g.load_actions LLDOSwiftHelper/lldb_actions
- Check Automatically continue
- Right click the created breakpoint and select Share
- Develop them like any other code in a Xcode project
- Run an application and pause it to start LLDB
- Use the
load_swift
command to load the file - Call your helpers
- GOTO 1 (unfortunately loading a files twice in a LLDB session results in duplicate symbols)
- Create a Python script containing the command code
- Use the
import
alias in your.lldbinit
to activate it - Run an application and pause it to start LLDB
reload_lldbinit
- Run your command
- Modify as needed
- GOTO 4 (reloading and re-defining commands in a LLDB session works just fine)
This purpose of this project is only to make debugging and development easier. Do NOT include it in your releases.
- Check out Chisel
- use
j[ump] +N
instead ofthread jump --by N
MIT - see LICENSE file