advanced ios debbuging

73
[email protected] Massimo Oliviero Advanced iOS Debugging @maxoly #code12

Upload: massimo-oliviero

Post on 10-May-2015

2.452 views

Category:

Technology


0 download

DESCRIPTION

The debug process constitutes an important part in an app's development cycle. Knowing the (right) tools and techniques means you can optimizes time and therefore costs. In this session we will see a number of techniques to optimize debugging of iOS applications exploiting the power of Xcode, LLDB and other support tools.

TRANSCRIPT

Page 1: Advanced iOS debbuging

[email protected]

Massimo Oliviero

Advanced iOS Debugging

@maxoly #code12

Page 2: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

Massimo Oliviero

Freelance Software Developer

Co-founder of #pragma mark http://pragmamark.org

Online

web http://www.massimooliviero.net

email [email protected]

twitter @maxoly

slide http://www.slideshare.net/MassimoOliviero

Page 3: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

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

Page 4: Advanced iOS debbuging

Advanced iOS Debugging

Code

Page 5: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

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(@"Array: %@", array);

NSLog(@"User: %@", user);

NSLog(@"User: %@", user);NSLog(@"User: %@", user);

NSLog(@"User: %@", user);

NSLog(@"User: %@", user);

NSLog(@"User: %@", user);

NSLog(@"User: %@", user);

Page 6: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

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)

Page 7: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

NSLog optimization

• Use convenient macro

• Use string conversions

• Try alternative frameworks

Page 8: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

NSLog macro

#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

Page 9: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

NSLog macro

• Enables DEBUG mode output only

• Outputs function name and line number

• Place macro into .pch file or in a header file

• You can use other macros like __ FILE__ (for example)

Page 10: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

String conversion functions

CGPoint point = CGPointMake(10.5f, 12.3f);NSLog(@"point: %@", NSStringFromCGPoint(point));

AdvanceDebuggingExample[3050:c07] point: {10.5, 12.3}

AdvanceDebuggingExample.m

Console

Page 11: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

String conversion functions

Returns a string formatted to contain the data from a structure:

• NSStringFromCGAffineTransform

• NSStringFromCGPoint

• NSStringFromCGRect

• NSStringFromCGSize

• NSStringFromUIEdgeInsets

• NSStringFromUIOffset

Page 12: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

Try alternative frameworks

• CocoaLumberjackhttps://github.com/robbiehanson/CocoaLumberjack

• NSLoggerhttps://github.com/fpillet/NSLogger

• DMLoggerhttps://github.com/malcommac/DMLogger

Page 13: Advanced iOS debbuging

Advanced iOS Debugging

Demo

Page 14: Advanced iOS debbuging

Advanced iOS Debugging

Xcode

Page 15: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

Xcode

• Configure your Behaviors

• Print more information with Arguments

• Go beyond logging with Breakpoints

Page 16: Advanced iOS debbuging

Advanced iOS Debugging

Behaviors

Page 17: Advanced iOS debbuging

Xcode default Behaviors

Debugger bar

Page 18: Advanced iOS debbuging

Xcode default Behaviors

Variables View Console

Debugger Navigator

Page 19: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

Xcode Behaviors

• Match Xcode to your Workflow

• Use Behaviors to control Xcode

• Behaviors lets you specify what should happen when a variety of events occur (like Run)

Page 20: Advanced iOS debbuging

Behaviors

When pauses

Show Debug NavigatorShow debugger views

Page 21: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

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

Page 22: Advanced iOS debbuging

Advanced iOS Debugging

Demo

Page 23: Advanced iOS debbuging

Advanced iOS Debugging

Arguments

Page 24: Advanced iOS debbuging

Arguments

Product > Scheme > Edit Scheme > Arguments

Page 25: Advanced iOS debbuging

Core Data Logging

-com.apple.CoreData.SQLDebug 1

Page 26: Advanced iOS debbuging

Core Data and iCloud

-com.apple.coredata.ubiquity.logLevel 3

Page 27: Advanced iOS debbuging

Advanced iOS Debugging

Breakpoints

Page 28: Advanced iOS debbuging

Creating and editing breakpoint

Page 29: Advanced iOS debbuging

Breakpoint Navigator

Page 30: Advanced iOS debbuging

Exception Breakpoint

Page 31: Advanced iOS debbuging

Symbolic Breakpoint

Page 32: Advanced iOS debbuging

Breakpoint Action

Page 33: Advanced iOS debbuging

Breakpoint action

Condition to evaluateThe num of time to ignore breakpoint before stoping

Log Message Action

Debugger Command Action

Play soundContinue program execution

Page 34: Advanced iOS debbuging

Debugger Command Action

po variable

expr (void)NSLog(@”variable: %@”, variable)

breakpoint set -f ADEMasterViewController.m -l 83

Page 35: Advanced iOS debbuging

Sharing Breakpoint

Share breakpoints with the team, so that all can benefit from it

This action will create a new directory to be committed in the repositoryAdvanceDebuggingExample.xcodeproj/xcshareddata/

Page 36: Advanced iOS debbuging

Advanced iOS Debugging

Demo

Page 37: Advanced iOS debbuging

Advanced iOS Debugging

LLDB

Page 38: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

Why LLDB

• Consistent Command Syntax

• Scriptability with Python

• Performance

• ...

Page 39: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

LLDB Commands

print object po [object]

print variable print [variable]

assign value expr [variable] = [value]

(lldb) <command>

Page 40: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

LLDB Commands

set breakpoint breakpoint set -f [file] -l [line]

load script command script import ~/test.py

evaluate expression expr <expression>

<noun> <verb> [-options [option-value]] [argument [argument...]]

Page 41: Advanced iOS debbuging

Custom object, the problem

No summary for custom object

@interface ADEEvent : NSObject

@property (nonatomic, strong) NSString *title;@property (nonatomic, strong) NSDate *when;

@endADEEvent *event = [[ADEEvent alloc] init];event.title = @"Codemotion Conference";event.when = [NSDate date];

Init object

Custom object

Page 42: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

Custom summary

• 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 file

Page 43: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

Custom summary

import lldb

def ade_summary(valobj, internal_dict):! titleAsString = valobj.GetChildMemberWithName('_title').GetSummary()! whenAsString = valobj.GetChildMemberWithName('_when').GetSummary()! return 'Title: ' + titleAsString + ' - when: ' + whenAsString

def __lldb_init_module(debugger, dict): debugger.HandleCommand('type summary add ADEEvent -F CustomSummaries1.ade_summary')

• Create “ADEEvent_summary.py” in Xcode project

• Then load script:(lldb) command script import /path/to/ADEEvent_summary.py

Page 44: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

Console tips

(lldb) po [self.view recursiveDescription]$7 = 0x082a2c60 <UITableView: 0x8971000; frame = (0 0; 320 504); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x8184be0>; layer = <CALayer: 0x8184570>; contentOffset: {0, 0}> | <UITableViewCell: 0x8282900; frame = (0 176; 320 44); text = '2013-03-12 21:22:34 +0000'; autoresize = W; layer = <CALayer: 0x8282a30>> | | <UITableViewCellContentView: 0x8282a60; frame = (0 0; 300 43); gestureRecognizers = <NSArray: 0x8282c30>; layer = <CALayer: 0x8282ac0>> | | | <UILabel: 0x8282e50; frame = (10 0; 280 43); text = '2013-03-12 21:22:34 +0000'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x8282ee0>>

| | <UIButton: 0x8282c80; frame = (290 0; 30 43); opaque = NO; userInteractionEnabled = NO; layer = ...

(lldb) po [[UIWindow keyWindow] recursiveDescription]$5 = 0x08273bc0 <UIWindow: 0x8181010; frame = (0 0; 320 568); layer = <UIWindowLayer: 0x81810e0>> | <UILayoutContainerView: 0xd06eed0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0xd071460>> | | <UINavigationTransitionView: 0xd09e850; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0xd09e920>> | | | <UIViewControllerWrapperView: 0x846e160; frame = (0 64; 320 504); autoresize = W+H; layer = <CALayer: 0x846e210>>...

Page 45: Advanced iOS debbuging

Advanced iOS Debugging

Demo

Page 46: Advanced iOS debbuging

Advanced iOS Debugging

Tools

Page 47: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

Tools

• Network Link Conditioner

• Charles

• PonyDebugger

• Deploymate

Page 48: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

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”

Page 49: Advanced iOS debbuging

Network Link Conditioner

Page 51: Advanced iOS debbuging

Charles

Page 52: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

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

Page 53: Advanced iOS debbuging

PonyDebugger

Page 54: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

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

Page 55: Advanced iOS debbuging

Deploymate

Page 56: Advanced iOS debbuging

Advanced iOS Debugging

Demo

Page 57: Advanced iOS debbuging

Advanced iOS Debugging

Remote

Page 58: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

Remote debugging

• Apple Crash Reports

• PLCrashReporter

• TestFlight

Page 59: Advanced iOS debbuging

Advanced iOS Debugging

Apple Crash Reports

Page 60: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

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 file that was generated when that binary was built. This must be an exact match

https://itunesconnect.apple.com

Page 61: Advanced iOS debbuging

Apple Crash Reports

Page 62: Advanced iOS debbuging

Apple Crash Reports

Page 63: Advanced iOS debbuging

Xcode Symbolication

Page 64: Advanced iOS debbuging

Advanced iOS Debugging

PLCrashReporter

Page 65: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

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/

Page 66: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

- (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); }

Page 67: Advanced iOS debbuging

Advanced iOS Debugging

TestFlight

Page 68: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

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://testflightapp.com/

Page 69: Advanced iOS debbuging

TestFlight Apps Managment

Page 70: Advanced iOS debbuging

TestFlight Crashes

Page 71: Advanced iOS debbuging

Advanced iOS Debugging

Final Thoughts

Page 72: Advanced iOS debbuging

Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly

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

Page 73: Advanced iOS debbuging

Advanced iOS Debugging

Thank you!

Massimo [email protected]

http://www.massimooliviero.net

follow me on twitter @maxolyhttp://www.slideshare.net/MassimoOlivierohttps://speakerdeck.com/massimooliviero