advanced ios debbuging (reloaded)
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
Advanced iOS DebuggingMassimo Oliviero
Massimo Oliviero
Freelance Software Developer
web http://www.massimooliviero.netemail [email protected] http://www.slideshare.net/MassimoOlivierotwitter @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
‣ Resources, links and videos
Source code
KimeraA simple iOS application for educational purpose
https://github.com/maxoly/Kimera
Code
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: %@", user);
NSLog(@"User: %@", user);NSLog(@"User: %@", user);
NSLog(@"User: %@", user);
NSLog(@"User: %@", user);
NSLog(@"User: %@", user);
NSLog(@"User: %@", user);
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)
NSLog optimization
‣ Use convenient macro
‣ Use string conversion functions
‣ Try alternative frameworks
#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
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)
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
String conversion functions
‣ NSStringFromCGAffineTransform
‣ NSStringFromCGPoint
‣ NSStringFromCGRect
‣ NSStringFromCGSize
‣ NSStringFromUIEdgeInsets
‣ NSStringFromUIOffset
Try alternative framworks
‣ CocoaLumberjack https://github.com/robbiehanson/CocoaLumberjack
‣ NSLoggerhttps://github.com/fpillet/NSLogger
‣ DMLoggerhttps://github.com/malcommac/DMLogger
Demo
Xcode
Xcode
‣ Con!gure your Behaviors
‣ Print more information with Arguments
‣ Push the limit with Build Settings
‣ Go beyond logging with Breakpoints
Behaviors
Xcode default
Debugger bar
Xcode default Behaviors
Variables View Console
Debugger Navigator
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)
Behaviors
When pauses
Show Debug NavigatorShow debugger views
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
Demo
Arguments
Arguments
Product > Scheme > Edit Scheme > Arguments
Core Data Logging
-com.apple.CoreData.SQLDebug 1
Core Data and iCloud logging
-com.apple.coredata.ubiquity.logLevel 3
Build Settings
Enable Static Analyzer
Treat Warning as Error
Warnings
Warnings - Objective-C
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 Actionpo variable
expr (void)NSLog(@”variable: %@”, variable)
breakpoint set -f ADEMasterViewController.m -l 83
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/
Demo
LLDB
Why LLDB
‣ Consistent Command Syntax
‣ Scriptability with Python
‣ Performance
‣ ...
LLDB Commands
print object po [object]
print variable print [variable]
assign value expr [variable] = [value]
(lldb) <command>
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 KMRMArgument : NSObject
@property (nonatomic, strong) NSString *name;@property (nonatomic, strong) NSDate *detail;
@endKMRMArgument *argument = [[KMRMArgument alloc] init];argument.title = @"Debugging";argument.when = @"Some advance techniques";
Init object
Custom object
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
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')
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>>...
Demo
Tools
Tools
‣ Network Link Conditioner
‣ Charles
‣ PonyDebugger
‣ Deploymate
‣ Spark Inspector
Network Link Conditioner
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
Charles
Charles Proxy
‣ It’s a web debugging proxy
‣ You can inspect, modify and record requests & responses
‣ SSL Proxinghttp://www.charlesproxy.com/documentation/faqs/ssl-connections-from-within-iphone-applications/
‣ http://www.charlesproxy.com
‣ Price start from US$50
Charles Proxy
PonyDebugger
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
Deploymate
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
Deploymate
Spark Inspector
Spark Inspector
‣ Runtime Debugger for iOS
‣ Monitor & Experiment in Real-time
‣ See Noti!cations in Real-time
‣ http://sparkinspector.com/
‣ Price € 31,79
Spark Inspector
Demo
Remote
Remote debugging
‣ Apple Crash Reports
‣ PLCrashReporter
‣ TestFlight
Apple Crash Reports
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
Apple Crash Reports
Apple Crash Reports
Xcode Symbolication
PLCrashReporter
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/
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); }
TestFlight
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
TestFlight Apps Management
TestFlight Crashes
Resources
Resources
‣ Links
‣ Videos
Links
Links
‣ Overview of iOS Crash Reporting Toolshttp://www.raywenderlich.com/33669/overview-of-ios-crash-reporting-tools-part-1http://www.raywenderlich.com/33669/overview-of-ios-crash-reporting-tools-part-2
‣ How to use Instruments in Xcodehttp://www.raywenderlich.com/23037/how-to-use-instruments-in-xcode
‣ Demystifying iOS Application Crash Loghttp://www.raywenderlich.com/23704/demystifying-ios-application-crash-logs
Links
‣ Intermediate Debugging with Xcode 4.5http://www.raywenderlich.com/28289/debugging-ios-apps-in-xcode-4-5
‣ Xcode LLDB Tutorialhttp://www.cimgf.com/2012/12/13/xcode-lldb-tutorial/
‣ iOS Simulator Tips & Trickshttp://mobile.tutsplus.com/tutorials/iphone/ios-simulator/
Links
‣ Compiler Warnings for Objective-C Developershttp://oleb.net/blog/2013/04/compiler-warnings-for-objective-c-developers/
‣ Defensive Programming in Cocoahttp://www.mikeash.com/pyblog/friday-qa-2010-08-27-defensive-programming-in-cocoa.html
‣ Testing and Debugging in iOS Simulatorhttps://developer.apple.com/library/ios/#documentation/IDEs/Conceptual/iOS_Simulator_Guide/TestingontheiOSSimulator/TestingontheiOSSimulator.html
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 Exampleshttp://llvm.org/svn/llvm-project/lldb/trunk/examples/
Videos
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
Final Thoughts
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
Thank you
Massimo [email protected]
http://www.massimooliviero.net
follow me on twitter @maxoly
http://www.slideshare.net/MassimoOlivierohttps://speakerdeck.com/massimooliviero