From SwiftTube Smart Debugging Talk 2018 and Advanced Debugging Techniques
brew install chisel
po [UIWindow.keyWindow recursiveDescription]
po [UIViewController _printHierarchy]
po [UIView _autolayoutTrace]
po [_UIViewLayoutFeedbackLoopDebugger layoutFeedbackLoopDebugger]
// lldb in Swift context:
expr -l objc++ -O -- [UIWindow.keyWindow recursiveDescription]
- Put this file in your home directory
- Add this to the file
command alias alt expr -l objc++ -O --[[UIWindow keyWiindow] _autolayoutTrace]
Command | Explanation |
---|---|
pa11y <aView> |
Print accessibility labels |
alamborder |
Highlight views with ambiguous layout |
pproperties |
Print the properties of an instance |
slowanim |
Slows down animiations. Sim + Device |
showimage |
Open a UIImage in Preview.app |
pactions <control> |
Print the actions/targets of a control |
findinstances UIView subviews.@count == 0
findinstances NSArray @count > 100
findinstances UIScrollViewDelegate
findinstances UIView window == nil || hidden == true ||
alpha == 0 || layer.bounds.#size.width == 0 || layer.bounds.#size.height == 0
Always run the analyzer and make sure you don't have any warnings.
Checker | Explanation |
---|---|
alpha.core.BoolAssignment |
Warn about assining non-{0, 1} values to Boolean variables |
alpha.clone.CloneChecker |
Reports similar pieces of code |
alpha.cplusplus.MisusedMovedObject |
Method calls on a moved-from object and copying a moved-from object will be reported |
optin.osx.cocoa.localizability.NonLocalizedStringChecker |
Warns about uses of non-localized NSStrings passed to UI methods expecting localized NSStrings |
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
...
#pragma clang diagnostic pop
- Address Sanitizer
- Undefined Behavior Sanitizer
- Main Thread Checker
- Thread Sanitizer (10-50x slower performance when running)
Advanced options are available NOT in the UI.
This is a small tool that the author created
class_setSuperclass
- Try the command
register read
(Where to find a list of them ...?)
- Layout Feedback Loop Debugger
- For more details, check out
-
-UIViewLayoutFeedbackLoopDebuggingThreshold 100 // 50...1000
- Logs to com.apple.UIKit:LayoutLoop
-
-NSViewLayoutFeedbackLoopDebuggingThreshold 100 // 50...1000
- Logs to com.apple.AppKit:LayoutLoop
- ConcurrencyDebug
-com.apple.CoreData.ConcurrencyDebug 1
Core Data Concurrency Debugging
-
Migrationdebug & SQLDebug
com.apple.CoreData.MigrationDebug 1
com.apple.CoreData.SQLDebug 3
-
NSTraceEvents
- `/Applications/TextEdit.app/Contents/MacOS/TextEdit -NSTraceEvents YES
if UserDefaults.standard.bool(forKey: "skip_onboarding") {
// Load main screen
}
if ProcessInfo.processInfo.arguments.contains("skip_onboarding") {
// Load main screen
}
let environment = ProcessInfo.processInfo.environment
if let serverUrl = environment["server_url"] {
// Set server URL with the value in the environment
}
else {
// Set the default one
}
let colorObservation = textFieldBackground.observe(\.backgroundColor, options:[.old, .new]) { (_, change) in
log.debug("Color: \(change.oldValue) -> \(change.newValue)")
log.debug("")
(lldb) po UIApplication.shared
error: property 'shared' not found on object 'UIApplication'
- in LLDB, there is an Objective-C context and a Swift context.
- The default is Objective-C
(lldb) expr -l swift -O -- UIApplication.shared
(lldb) expr @import UIKit
(lldb) expr @import Foundation
A symbolic breakpoint on UIApplicationMain! (Move into User Breakpoints)
Then, send 2 "Actions: Debugger command"
expr @import UIKit
and
expr @import Foundation
- Print out your first argument
- Break: On Throw
- Debugger Command
- po $arg1
Debugging Swift code with LLDB
- With Python LLDB Python Scripting
- A collection of handy lldb commands
- Install via brew
- paltrace
- AUTO LAYOUT TRACEC
- paltrace
assert()
func transformString(string: String?) -> String {
assert(string != nil, "Invalid parameter")
return string! + "_transform"
}
assertionFailure()
switch flippy {
case foo:
Do something
case bar:
Do something else
default:
assertionFailure("We are not handling a FooBar, add it to the cases!)
}
assertionFailure("Something is wrong, did you fail to configure BLAH?")