Skip to content

Instantly share code, notes, and snippets.

@perlguy99
Last active July 28, 2021 07:21
Show Gist options
  • Save perlguy99/02d213adfe3b89e3e7067bfea94501ea to your computer and use it in GitHub Desktop.
Save perlguy99/02d213adfe3b89e3e7067bfea94501ea to your computer and use it in GitHub Desktop.
Debugging Hints, Tips, Tricks

iOS Debugging Tips/Tricks/Hints

From SwiftTube Smart Debugging Talk 2018 and Advanced Debugging Techniques

brew install chisel

LLDB View Debugging

po [UIWindow.keyWindow recursiveDescription]
po [UIViewController _printHierarchy]
po [UIView _autolayoutTrace]
po [_UIViewLayoutFeedbackLoopDebugger layoutFeedbackLoopDebugger]

// lldb in Swift context:
expr -l objc++ -O -- [UIWindow.keyWindow recursiveDescription]

.lldbinit

  • Put this file in your home directory
  • Add this to the file

command alias alt expr -l objc++ -O --[[UIWindow keyWiindow] _autolayoutTrace]

github.com/facebook/chisel

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

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

CLang Analyzer

Always run the analyzer and make sure you don't have any warnings.

clang -cc1 -analyzer-checker-help

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

Opt out of warnings for a specific code region

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
...
#pragma clang diagnostic pop

clang Sanitizers

  • Address Sanitizer
  • Undefined Behavior Sanitizer
  • Main Thread Checker
  • Thread Sanitizer (10-50x slower performance when running)

Advanced options are available NOT in the UI.

Retrain Tracker

This is a small tool that the author created

class_setSuperclass

Advanced Debugging Techniques

In lldb

  • Try the command register read

Launch Arguments (Launch arguments can be passed at runtime!)

(Where to find a list of them ...?)

UIView / Views

  • Layout Feedback Loop Debugger
    • For more details, check out

What's New in AutoLayout

  • -UIViewLayoutFeedbackLoopDebuggingThreshold 100 // 50...1000

    • Logs to com.apple.UIKit:LayoutLoop
  • -NSViewLayoutFeedbackLoopDebuggingThreshold 100 // 50...1000

    • Logs to com.apple.AppKit:LayoutLoop

Core Data

  • 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

Custom Launch Arguments

iOS?

if UserDefaults.standard.bool(forKey: "skip_onboarding") {
    // Load main screen
}

macOS?

if ProcessInfo.processInfo.arguments.contains("skip_onboarding") {
    // Load main screen
}

The above may be for both, either via UserDefaults or arguments.

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
}

Using Keypaths to inspect even private things

let colorObservation = textFieldBackground.observe(\.backgroundColor, options:[.old, .new]) { (_, change) in 
    log.debug("Color: \(change.oldValue) -> \(change.newValue)")
    log.debug("")

In lldb, if you get an error...

(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

One way to fix this and use the Swift context...

(lldb) expr -l swift -O -- UIApplication.shared

An easier way...

(lldb) expr @import UIKit
(lldb) expr @import Foundation

An even better way...

A symbolic breakpoint on UIApplicationMain! (Move into User Breakpoints)

Then, send 2 "Actions: Debugger command"

expr @import UIKit

and

expr @import Foundation

-NSKVODeallocateBreak

On Exception Breakpoint

  • Print out your first argument
    • Break: On Throw
    • Debugger Command
      • po $arg1

A Bunch More User Breakpoint Examples...

User Breakpoints in Xcode

LLDB (Low Level Debugger)

Changing Variables at Runtime

Debugging Swift code with LLDB

Extending LLDB

Chisel (Facebook Chisel)

  • A collection of handy lldb commands
  • Install via brew
    • paltrace
      • AUTO LAYOUT TRACEC

How Can We Save Time?

Assertions

Assertions are ONLY there in DEBUG mode, they are ignored in PRODUCTION!

  • 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?")

Precondition & FatalError

These are for PRODUCTION code

@perlguy99
Copy link
Author

debugging_talk

@perlguy99
Copy link
Author

debugging_talk2

@perlguy99
Copy link
Author

Advanced_Debugging_ChangingVariablesAtRuntime
Advanced_Debugging_ExceptionBreakpoint
Advanced_Debugging_ExtendingLLDB
Advanced_Debugging_Lauch_Arguments
Advanced_Debugging_with_Chisel
AdvancedDebugging_Symbolic_Breakpoint

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment