Slide 1

Slide 1 text

Advanced iOS Debugging Massimo Oliviero

Slide 2

Slide 2 text

Massimo Oliviero Freelance Software Developer web http://www.massimooliviero.net email [email protected] slide http://www.slideshare.net/MassimoOliviero twitter @maxoly

Slide 3

Slide 3 text

Massimo Oliviero http://pragmamark.org/ La prima community di sviluppatori iOS e Mac OS X in Italia. https://www.facebook.com/groups/pragmamark/

Slide 4

Slide 4 text

Agenda ‣ Code, some tips for standard functions ‣ Xcode, the best tools for debugging ‣ LLDB, your great friend ‣ Tools, network debugging how to and more ‣ Remote, over the air debugging ‣ Resources, links and videos

Slide 5

Slide 5 text

Source code Kimera A simple iOS application for educational purpose https://github.com/maxoly/Kimera

Slide 6

Slide 6 text

Code

Slide 7

Slide 7 text

It all began... NSLog(@"Error :( %@", error); NSLog(@"User: %@", user); NSLog(@"Array: %@", array); NSLog(@"URL: %@", url); NSLog(@"Count: %i", count); NSLog(@"User %@", user); NSLog(@"Array %@", array); NSLog(@"Error :( %@", error); NSLog(@"Error :( %@", error NSLog(@"URL: %@", url); NSLog(@"Array: %@", array); NSLog(@"User: NSLog(@"User: %@", user); NSLog(@"User: %@", user); NSLog(@"User: %@", user); NSLog(@"User: %@", user); NSLog(@"User: %@", user); NSLog(@"User: %@", user);

Slide 8

Slide 8 text

NSLog ‣ It prints debugs output only to the console ‣ It’s a simple native Foundation function ‣ It’s not too bad, but It’s an ancient technique ‣ It slows things down considerably (if not handled)

Slide 9

Slide 9 text

NSLog optimization ‣ Use convenient macro ‣ Use string conversion functions ‣ Try alternative frameworks

Slide 10

Slide 10 text

#if defined DEBUG #define MYNSLog(s, ...) NSLog((@"%s [Line %d] " s), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define MYNSLog(s, ...) #endif -[TestViewController viewDidLoad] [Line 33] message - (void)viewDidLoad { [super viewDidLoad]; MYNSLog(@"message"); } MyGreatApp-prefix.pch TestViewController.m Console NSLog macro

Slide 11

Slide 11 text

NSLog macro ‣ Enables DEBUG mode output only ‣ Outputs function name and line number ‣ Place macro into .pch le or in a header le ‣ You can use other macros like __ FILE__ (for example)

Slide 12

Slide 12 text

CGPoint point = CGPointMake(10.5f, 12.3f); NSLog(@"point: %@", NSStringFromCGPoint(point)); AdvanceDebuggingExample[3050:c07] point: {10.5, 12.3} AdvanceDebuggingExample.m Console String conversion functions

Slide 13

Slide 13 text

String conversion functions ‣ NSStringFromCGAffineTransform ‣ NSStringFromCGPoint ‣ NSStringFromCGRect ‣ NSStringFromCGSize ‣ NSStringFromUIEdgeInsets ‣ NSStringFromUIOffset

Slide 14

Slide 14 text

Try alternative framworks ‣ CocoaLumberjack https://github.com/robbiehanson/CocoaLumberjack ‣ NSLogger https://github.com/fpillet/NSLogger ‣ DMLogger https://github.com/malcommac/DMLogger

Slide 15

Slide 15 text

Demo

Slide 16

Slide 16 text

Xcode

Slide 17

Slide 17 text

Xcode ‣ Con gure your Behaviors ‣ Print more information with Arguments ‣ Push the limit with Build Settings ‣ Go beyond logging with Breakpoints

Slide 18

Slide 18 text

Behaviors

Slide 19

Slide 19 text

Xcode default Debugger bar

Slide 20

Slide 20 text

Xcode default Behaviors Variables View Console Debugger Navigator

Slide 21

Slide 21 text

Xcode Behaviors ‣ Match Xcode to your Work ow ‣ Use Behaviors to control Xcode ‣ Behaviors lets you specify what should happen when a variety of events occur (like Run)

Slide 22

Slide 22 text

Behaviors When pauses Show Debug Navigator Show debugger views

Slide 23

Slide 23 text

Change default Behavior For example, when Running pauses: ‣ show the Breakpoint Navigator instead of Debug Navigator ‣ show only Variable Views ‣ open another tab only with Console view

Slide 24

Slide 24 text

Demo

Slide 25

Slide 25 text

Arguments

Slide 26

Slide 26 text

Arguments Product > Scheme > Edit Scheme > Arguments

Slide 27

Slide 27 text

Core Data Logging -com.apple.CoreData.SQLDebug 1

Slide 28

Slide 28 text

Core Data and iCloud logging -com.apple.coredata.ubiquity.logLevel 3

Slide 29

Slide 29 text

Build Settings

Slide 30

Slide 30 text

Enable Static Analyzer

Slide 31

Slide 31 text

Treat Warning as Error

Slide 32

Slide 32 text

Warnings

Slide 33

Slide 33 text

Warnings - Objective-C

Slide 34

Slide 34 text

Breakpoints

Slide 35

Slide 35 text

Creating and editing breakpoint

Slide 36

Slide 36 text

Breakpoint Navigator

Slide 37

Slide 37 text

Exception Breakpoint

Slide 38

Slide 38 text

Symbolic Breakpoint

Slide 39

Slide 39 text

Breakpoint Action

Slide 40

Slide 40 text

Breakpoint Action Condition to evaluate The num of time to ignore breakpoint before stoping Log Message Action Debugger Command Action Play sound Continue program execution

Slide 41

Slide 41 text

Debugger Command Action po variable expr (void)NSLog(@”variable: %@”, variable) breakpoint set -f ADEMasterViewController.m -l 83

Slide 42

Slide 42 text

Sharing Breakpoint Share breakpoints with the team, so that all can bene t from it This action will create a new directory to be committed in the repository AdvanceDebuggingExample.xcodeproj/xcshareddata/

Slide 43

Slide 43 text

Demo

Slide 44

Slide 44 text

LLDB

Slide 45

Slide 45 text

Why LLDB ‣ Consistent Command Syntax ‣ Scriptability with Python ‣ Performance ‣ ...

Slide 46

Slide 46 text

LLDB Commands print object po [object] print variable print [variable] assign value expr [variable] = [value] (lldb)

Slide 47

Slide 47 text

LLDB Commands set breakpoint breakpoint set -f [file] -l [line] load script command script import ~/test.py evaluate expression expr [-options [option-value]] [argument [argument...]]

Slide 48

Slide 48 text

Custom Object, the problem No summary for custom object @interface KMRMArgument : NSObject @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSDate *detail; @end KMRMArgument *argument = [[KMRMArgument alloc] init]; argument.title = @"Debugging"; argument.when = @"Some advance techniques"; Init object Custom object

Slide 49

Slide 49 text

Custom Summary, the solution ‣ Create a Python script that will instruct LLDB on how to display a summary of your custom object ‣ Load your Python script via command line or ~/.lldbinit le

Slide 50

Slide 50 text

Custom Summary ‣ Create “KMRMArgument_summary.py” in Xcode project ‣ Then load script: (lldb) command script import /path/to/KMRMArgument_summary.py import lldb def arg_summary(valobj, internal_dict): ! nameAsString = valobj.GetChildMemberWithName('_name').GetSummary() ! detailAsString = valobj.GetChildMemberWithName('_detail').GetSummary() ! return 'Title: ' + nameAsString + ' - detail: ' + detailAsString def __lldb_init_module(debugger, dict): debugger.HandleCommand('type summary add KRMRArgument -F KRMRArgument_summary.arg_summary')

Slide 51

Slide 51 text

Console tips (lldb) po [self.view recursiveDescription] $7 = 0x082a2c60 ; layer = ; contentOffset: {0, 0}> | > | | ; layer = > | | | > | | > | > | | > | | | > ...

Slide 52

Slide 52 text

Demo

Slide 53

Slide 53 text

Tools

Slide 54

Slide 54 text

Tools ‣ Network Link Conditioner ‣ Charles ‣ PonyDebugger ‣ Deploymate ‣ Spark Inspector

Slide 55

Slide 55 text

Network Link Conditioner

Slide 56

Slide 56 text

Network Link Conditioner ‣ It’s a utility that enables you to simulate network conditions ‣ To install just select Xcode > Open Developer Tool > More Developer Tools. You’ll be taken to Apple’s developer downloads site ‣ Download “Hardware IO Tools for Xcode”

Slide 57

Slide 57 text

Network Link Conditioner

Slide 58

Slide 58 text

Charles

Slide 59

Slide 59 text

Charles Proxy ‣ It’s a web debugging proxy ‣ You can inspect, modify and record requests & responses ‣ SSL Proxing http://www.charlesproxy.com/documentation/faqs/ssl-connections- from-within-iphone-applications/ ‣ http://www.charlesproxy.com ‣ Price start from US$50

Slide 60

Slide 60 text

Charles Proxy

Slide 61

Slide 61 text

PonyDebugger

Slide 62

Slide 62 text

PonyDebugger ‣ Network Traffic Debugger ‣ Core Data Browser ‣ It is a client library and gateway server combination that uses Chrome Developer Tools on your browser to debug your application's network traffic and managed object contexts. ‣ https://github.com/square/PonyDebugger

Slide 63

Slide 63 text

PonyDebugger

Slide 64

Slide 64 text

Deploymate

Slide 65

Slide 65 text

Deploymate ‣ If using an API introduced later than your target OS but your app is targeting an older OS version, Xcode doesn't warn you about it ‣ It helps identify unavailable, deprecated and obsolete API ‣ http://www.deploymateapp.com/ ‣ Price US$19.99

Slide 66

Slide 66 text

Deploymate

Slide 67

Slide 67 text

Spark Inspector

Slide 68

Slide 68 text

Spark Inspector ‣ Runtime Debugger for iOS ‣ Monitor & Experiment in Real-time ‣ See Noti cations in Real-time ‣ http://sparkinspector.com/ ‣ Price € 31,79

Slide 69

Slide 69 text

Spark Inspector

Slide 70

Slide 70 text

Demo

Slide 71

Slide 71 text

Remote

Slide 72

Slide 72 text

Remote debugging ‣ Apple Crash Reports ‣ PLCrashReporter ‣ TestFlight

Slide 73

Slide 73 text

Apple Crash Reports

Slide 74

Slide 74 text

Apple Crash Reports ‣ For app published on App Store, you can acquire crash log from iTunes Connect and import it into Organizer for symbolication ‣ To symbolicate a crash log, Xcode needs to have access to the matching application binary that was uploaded to the App Store, and the .dSYM le that was generated when that binary was built. This must be an exact match ‣ https://itunesconnect.apple.com

Slide 75

Slide 75 text

Apple Crash Reports

Slide 76

Slide 76 text

Apple Crash Reports

Slide 77

Slide 77 text

Xcode Symbolication

Slide 78

Slide 78 text

PLCrashReporter

Slide 79

Slide 79 text

PLCrashReporter ‣ In-process CrashReporter framework for the iPhone and Mac OS X ‣ Handles both uncaught Objective-C exceptions and fatal signals ‣ Backtraces for all active threads are provided ‣ https://code.google.com/p/plcrashreporter/

Slide 80

Slide 80 text

PLCrashReporter - (void) handleCrashReport { PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter]; NSData *crashData; NSError *error; // Try loading the crash report crashData = [crashReporter loadPendingCrashReportDataAndReturnError: &error]; if (crashData == nil) { NSLog(@"Could not load crash report: %@", error); goto finish; } PLCrashReport *report = [[[PLCrashReport alloc] initWithData: crashData error: &error] autorelease]; if (report == nil) { NSLog(@"Could not parse crash report"); goto finish; } .... return; } // from UIApplicationDelegate protocol - (void) applicationDidFinishLaunching: (UIApplication *) application { PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter]; NSError *error; // Check if we previously crashed if ([crashReporter hasPendingCrashReport]) [self handleCrashReport]; // Enable the Crash Reporter if (![crashReporter enableCrashReporterAndReturnError: &error]) NSLog(@"Warning: Could not enable crash reporter: %@", error); }

Slide 81

Slide 81 text

TestFlight

Slide 82

Slide 82 text

TestFlight ‣ Invite your testers, drop in the SDK and start uploading your builds. ‣ Upload your builds and TestFlight takes care of the rest. Painless over-the-air distribution to your testers and distribution lists. ‣ Complete tracking of your build, from distribution to sessions, checkpoints and crashes. ‣ https://test ightapp.com

Slide 83

Slide 83 text

TestFlight Apps Management

Slide 84

Slide 84 text

TestFlight Crashes

Slide 85

Slide 85 text

Resources

Slide 86

Slide 86 text

Resources ‣ Links ‣ Videos

Slide 87

Slide 87 text

Links

Slide 88

Slide 88 text

Links ‣ Overview of iOS Crash Reporting Tools http://www.raywenderlich.com/33669/overview-of-ios-crash- reporting-tools-part-1 http://www.raywenderlich.com/33669/overview-of-ios-crash- reporting-tools-part-2 ‣ How to use Instruments in Xcode http://www.raywenderlich.com/23037/how-to-use-instruments-in- xcode ‣ Demystifying iOS Application Crash Log http://www.raywenderlich.com/23704/demystifying-ios-application- crash-logs

Slide 89

Slide 89 text

Links ‣ Intermediate Debugging with Xcode 4.5 http://www.raywenderlich.com/28289/debugging-ios-apps-in- xcode-4-5 ‣ Xcode LLDB Tutorial http://www.cimgf.com/2012/12/13/xcode-lldb-tutorial/ ‣ iOS Simulator Tips & Tricks http://mobile.tutsplus.com/tutorials/iphone/ios-simulator/

Slide 90

Slide 90 text

Links ‣ Compiler Warnings for Objective-C Developers http://oleb.net/blog/2013/04/compiler-warnings-for-objective-c- developers/ ‣ Defensive Programming in Cocoa http://www.mikeash.com/pyblog/friday-qa-2010-08-27-defensive- programming-in-cocoa.html ‣ Testing and Debugging in iOS Simulator https://developer.apple.com/library/ios/#documentation/IDEs/ Conceptual/iOS_Simulator_Guide/TestingontheiOSSimulator/ TestingontheiOSSimulator.html

Slide 91

Slide 91 text

Links ‣ iOS Debugging (slide by Dave Kozol) http://arbormoon.com/sites/default/ les/ ASIDebuggingCocoaConfChicago.pdf ‣ Strong, Better, Faster with Instruments and Debugging (slide by Kyle Richter) http://dragonforged.com/CocoaConf.pdf ‣ LLDB Script Examples http://llvm.org/svn/llvm-project/lldb/trunk/examples/

Slide 92

Slide 92 text

Videos

Slide 93

Slide 93 text

Videos ‣ WWDC 2012 - 415 - Debugging with LLDB ‣ WWDC 2011 - 321 - Migrating from GDB to LLDB ‣ WWDC 2010 - 316 - Debugging with Xcode 4 and LLDB ‣ NSScreenCast - 002 - Memory Problems

Slide 94

Slide 94 text

Final Thoughts

Slide 95

Slide 95 text

Final Thoughts ‣ Don’t use NSLog anymore ;) ‣ Create your Xcode Behaviors ‣ Breakpoints are your friends ‣ LLDB is a promising youngster ‣ Tools can save your life ‣ The QA phase is essential

Slide 96

Slide 96 text

Thank you Massimo Oliviero [email protected] http://www.massimooliviero.net follow me on twitter @maxoly http://www.slideshare.net/MassimoOliviero https://speakerdeck.com/massimooliviero