Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Learn to Debug Like a Pro

Learn to Debug Like a Pro

If your idea of debugging is breakpoints and print() calls, this session will help show you more advanced techniques to catch bugs faster. You’ll learn about watch points, assertions, conditional breakpoints, and more – all with the goal of helping you find and fix bugs faster.

Presented at Appdevcon 2018, Amsterdam.

Paul Hudson

March 16, 2018
Tweet

More Decks by Paul Hudson

Other Decks in Programming

Transcript

  1. PAUL HUDSON — @twostraws LEARN TO DEBUG LIKE A PRO

    https://www.hackingwithswift.com
  2. ▸ @twostraws on Twitter ▸ twostraws on GitHub ▸ twostraws

    on Reddit ▸ twostraws on StackOverflow ▸ [email protected] GET IN TOUCH!
  3. If you do nothing else after
 listening to this talk…

    Count how many calls to assert() you already have, then work to double that figure
  4. 246

  5. public func fatalError( _ message: @autoclosure () -> String =

    String(), file: StaticString = #file, line: UInt = #line ) -> Never
  6. public func fatalError( _ message: @autoclosure () -> String =

    String(), file: StaticString = #file, line: UInt = #line ) -> Never
  7. ▸ Dequeue cells. ▸ Instantiate from storyboards. ▸ Read the

    app bundle. HANDLING LOGIC ERRORS Trying to recover at runtime just masks the problem
  8. (lldb) p someInt (Int) $R0 = 10 (lldb) po someObject

    <App.ExampleObj: 0x7ff4f0014260> (lldb)
  9. <App.ExampleObj: 0x7ff4f0014260> (lldb) (lldb) p someObject (App.ExampleObj) $R1 = 0x00007fdd10817200

    { username = “twostraws” favoriteSongs = 25 values { [0] = “Shake it Off”
  10. enum BreakpointManager { static let firstRun = 0 static let

    userCreate = 0 static let userLogin = 0 static let subscribe = 0 }
  11. enum BreakpointManager { static let firstRun = 0 static let

    userCreate = 0 static let userLogin = 0 static let subscribe = 0 }
  12. enum BreakpointManager { static let firstRun = 0 static let

    userCreate = 1 static let userLogin = 0 static let subscribe = 0 }
  13. UIApplicationMain + 159 23 Project38 0x0000000102a52b47 main + 55 24

    libdyld.dylib 0x000000010879dd81 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)
  14. 2018-03-14 08:16:53.226319+0000 Project38[82247:4984913] *** Terminating app due to uncaught exception

    'NSInvalidArgumentException', reason: 'Storyboard (<UIStoryboard: 0x60800006f6c0>) doesn't contain a view controller with identifier 'Detail'' *** First throw call stack: ( 0 CoreFoundation
  15. 2018-03-14 08:16:53.226319+0000 Project38[82247:4984913] *** Terminating app due to uncaught exception

    'NSInvalidArgumentException', reason: 'Storyboard (<UIStoryboard: 0x60800006f6c0>) doesn't contain a view controller with identifier 'Detail'' *** First throw call stack: ( 0 CoreFoundation
  16. What’s making this variable change? Let’s find out… [Step Over]

    [Step Over] [Step Over] [Step Over] [Step Over] [Step Over] [Step Over] [Step Over] [Step Over] [Step Over] [Step Over] [Step Over]
  17. BREAKPOINTS Pause when a location is reached
 or when an

    event happens Pause when a value is changed by
 any part of your code WATCHPOINTS
  18. ▸ The view debugger ▸ Recursive descriptions ▸ Identifying constraints

    ▸ Exercising ambiguity ▸ Layout feedback loops ▸ Pseudolanguages DEBUGGING LAYOUTS
  19. 1

  20. 2

  21. <UIView: 0x7fd501f044b0; frame = (0 0; 736 414); autoresize =

    W+H; layer = <CALayer: 0x604000034b20>> | <UIView: 0x7fd501f04690; frame = (0 64; 375 470); autoresize = RM+BM; layer = <CALayer: 0x604000034b60>> | | <UIImageView: 0x7fd501f04250; frame = (10 10; 355 450); autoresize = RM+BM;
  22. VIEW DEBUGGER LLDB Fancy 3D effects Includes VCs Shows constraints

    Filters Plain text Shows all values Great for diffs
  23. 3

  24. "<NSLayoutConstraint:0x6040000912b0 ‘Prompt Leading' H:|-(0)-[UIView:0x7fd5cdc0a6b0] (active, names: '|':UIView:0x7fd5cdc0a8b0 )>", "<NSLayoutConstraint:0x6040000913a0 ‘Prompt

    Trailing' H:[UIView:0x7fd5cdc0a8b0]-(0)- [UIView:0x7fd5cdc0a6b0] (active)>", "<NSLayoutConstraint:0x608000090cc0 'UIView- Encapsulated-Layout-Width' UIView: 0x7fd5cdc0a8b0.width == 375 (active)>”
  25. "<NSLayoutConstraint:0x6040000912b0 ‘Prompt Leading' H:|-(0)-[UIView:0x7fd5cdc0a6b0] (active, names: '|':UIView:0x7fd5cdc0a8b0 )>", "<NSLayoutConstraint:0x6040000913a0 ‘Prompt

    Trailing' H:[UIView:0x7fd5cdc0a8b0]-(0)- [UIView:0x7fd5cdc0a6b0] (active)>", "<NSLayoutConstraint:0x608000090cc0 'UIView- Encapsulated-Layout-Width' UIView: 0x7fd5cdc0a8b0.width == 375 (active)>”
  26. 4

  27. *UIView:0x7fad2d7039e0- AMBIGUOUS LAYOUT for UIView:0x7fad2d7039e0.minX{id: 45} LEGEND * - is

    laid out with auto layout + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES • - layout engine host
  28. *UIView:0x7fad2d7039e0- AMBIGUOUS LAYOUT for UIView:0x7fad2d7039e0.minX{id: 45} LEGEND * - is

    laid out with auto layout + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES • - layout engine host
  29. 5

  30. ▸ Disabled by default. ▸ When enabled, allows views to

    run layout X times. ▸ You choose the value of X. ▸ It runs a little more to collect info, then throws an error. FEEDBACK LOOP DEBUGGER
  31. 1. The call stack each time layout took place. 2.

    Which views were laid out and in which order. 3. Whether ambiguous layout was part of the problem.
  32. 6

  33. ▸ print() is fine for basic work, but there are

    better alternatives ▸ All codebases need more assert()s ▸ fatalError() makes cleaner code ▸ Know when to use p, po, expr, and frame variable THE BASICS
  34. ▸ Stop adding and deleting the same breakpoints: conditions! ▸

    Play sounds to help you track invisible operation state ▸ Always use exception breakpoints ▸ Watchpoints will save you time BREAKPOINTS AND WATCHPOINTS
  35. ▸ You’re not alone: no one likes debugging layouts ▸

    Filter the view debugger ▸ Always use constraint identifiers ▸ Exercise ambiguity! ▸ Make Xcode detect layout loops LAYOUTS
  36. ▸ This is best done in Instruments, but Xcode can

    help ▸ The basic memory graph shows allocations and loops ▸ Enable Malloc Stack and Malloc Scribble to make it work harder! MEMORY
  37. PAUL HUDSON — @twostraws LEARN TO DEBUG LIKE A PRO

    https://www.hackingwithswift.com