advanced ios debbuging
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
Massimo Oliviero
Advanced iOS Debugging
@maxoly #code12
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
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
Advanced iOS Debugging
Code
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);
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)
Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly
NSLog optimization
• Use convenient macro
• Use string conversions
• Try alternative frameworks
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
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)
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
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
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
Advanced iOS Debugging
Demo
Advanced iOS Debugging
Xcode
Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly
Xcode
• Configure your Behaviors
• Print more information with Arguments
• Go beyond logging with Breakpoints
Advanced iOS Debugging
Behaviors
Xcode default Behaviors
Debugger bar
Xcode default Behaviors
Variables View Console
Debugger Navigator
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)
Behaviors
When pauses
Show Debug NavigatorShow debugger views
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
Advanced iOS Debugging
Demo
Advanced iOS Debugging
Arguments
Arguments
Product > Scheme > Edit Scheme > Arguments
Core Data Logging
-com.apple.CoreData.SQLDebug 1
Core Data and iCloud
-com.apple.coredata.ubiquity.logLevel 3
Advanced iOS Debugging
Breakpoints
Creating and editing breakpoint
Breakpoint Navigator
Exception Breakpoint
Symbolic Breakpoint
Breakpoint Action
Breakpoint action
Condition to evaluateThe num of time to ignore breakpoint before stoping
Log Message Action
Debugger Command Action
Play soundContinue program execution
Debugger Command Action
po variable
expr (void)NSLog(@”variable: %@”, variable)
breakpoint set -f ADEMasterViewController.m -l 83
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/
Advanced iOS Debugging
Demo
Advanced iOS Debugging
LLDB
Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly
Why LLDB
• Consistent Command Syntax
• Scriptability with Python
• Performance
• ...
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>
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...]]
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
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
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
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>>...
Advanced iOS Debugging
Demo
Advanced iOS Debugging
Tools
Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly
Tools
• Network Link Conditioner
• Charles
• PonyDebugger
• Deploymate
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”
Network Link Conditioner
Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly
Charles
• 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/
Charles
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
PonyDebugger
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
Deploymate
Advanced iOS Debugging
Demo
Advanced iOS Debugging
Remote
Massimo Oliviero - [email protected] - www.massimooliviero.net - @maxoly
Remote debugging
• Apple Crash Reports
• PLCrashReporter
• TestFlight
Advanced iOS Debugging
Apple Crash Reports
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
Apple Crash Reports
Apple Crash Reports
Xcode Symbolication
Advanced iOS Debugging
PLCrashReporter
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/
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); }
Advanced iOS Debugging
TestFlight
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/
TestFlight Apps Managment
TestFlight Crashes
Advanced iOS Debugging
Final Thoughts
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
Advanced iOS Debugging
Thank you!
Massimo [email protected]
http://www.massimooliviero.net
follow me on twitter @maxolyhttp://www.slideshare.net/MassimoOlivierohttps://speakerdeck.com/massimooliviero