Getting interactive with the debugger

One of the cool things about RubyMotion is that when you run your app you get a REPL (read, eval, print, loop) that you can quickly try some code out in. Although it’s not as easy to use, the debugger in Xcode (I’m using lldb) can give you some of the same experience when it comes to interrogating objects and trying basic things.

Here are some simple examples of techniques to use to help you out:

##Interrogation

I can never remember how I’m supposed to spell font names when using +[UIFont fontWithName:size:], so I’ll often just set a break point anywhere to get me into the debugger and then ask UIFont:

(lldb) po [UIFont familyNames]
(id) $1 = 0x06a9e450 <__NSCFArray 0x6a9e450>(
Thonburi,
Snell Roundhand,
Academy Engraved LET,

... snip

Oriya Sangam MN,
Didot,
Bodoni 72 Smallcaps
)

This is cool but I’m lazy and I want this output sorted so I don’t have to scan up and down

(lldb) po [[UIFont familyNames] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]
(id) $2 = 0x06aa28f0 <__NSArrayI 0x6aa28f0>(
Academy Engraved LET,
American Typewriter,
Apple Color Emoji,
Apple SD Gothic Neo,
 
... snip

Verdana,
Zapf Dingbats,
Zapfino
)

Now that’s much easier to look at.

Just a quick note there are a couple of ways I could have done this. I used [UIFont familyNames] nested inside the sortedArrayUsingSelector: method, but I could have just as easily used

  • The memory address of the originally returned array [0x06a9e450 sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]
  • The variable that the result of the first expression was assigned to [$1 sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]

Now I’m deeply saddened that Comic sans is not in this list but I can see something that sounds equally as awesome “Chalkboard SE”. So to answer my original question and find out what I need to use in my +[UIFont fontWithName:size:] I will again ask UIFont:

(lldb) po [UIFont fontNamesForFamilyName:@"Chalkboard SE"]
(id) $1 = 0x06a84670 <__NSCFArray 0x6a84670>(
ChalkboardSE-Regular,
ChalkboardSE-Bold,
ChalkboardSE-Light
)

Excellent now I know the exact string I need to be using for the different weights.

Make sure you see beyond the example above and the see the power of interrogating objects and calling their methods.

##Changing values

Sometimes you want to just jump in and see how changing a value effects something without rebuilding. Again you can actually do a fair amount in the debugger

###Scalar values

If in my program I had

-[SomeAwesomeViewController viewDidAppear:]

- (void)viewDidAppear:(BOOL)animated;
{
  CGFloat   someFloat   = 5.f;
  NSInteger someInteger = 10;
  
  ...
}

I can add a breakpoint just after the assignments and then change both of these values using expr

expr someFloat   = 4.32
expr someInteger = 20

To confirm the change I can inspect with

(lldb) p someFloat
(CGFloat) $1 = 4.32
(lldb) p someInteger
(NSInteger) $2 = 20

###Objects

I can also manipulate objects the same way

If I have the following code, which currently doesn’t work because the dateFormatter has the wrong format. I can find out what the format is and play around until I get the correct result:

-[SomeAwesomeViewController viewDidAppear:]

- (void)viewDidAppear:(BOOL)animated;
{
  NSString *startDate = @"2012-09-15";
  
  NSDate *date = [self.someDateFormatter dateFromString:startDate];
  
  ...
}

I add a breakpoint after the startDate is declared and then play. This is where we start to see that it can be a little tricky to make lldb do what we want

###1. Find out what the current dateFormat is

(lldb) po self.someDateFormatter.dateFormat
error: property 'dateFormat' not found on object of type 'NSDateFormatter *'
error: 1 errors parsing expression

So above we can see that dateFormat needs to be called as a method, :( no dot syntax this time…

(lldb) po [self.someDateFormatter dateFormat]
(id) $1 = 0x06d79cd0 dd/mm/yyyy

OK so we can now see why this is not working as the dateFormat is completely wrong for the input string. Let’s try a different format

(lldb) expr [self.someDateFormatter setDateFormat:@"yyyy-MM-dd"]
error: no known method '-setDateFormat:'; cast the message send to the method's return type
error: 1 errors parsing expression

Mmmm I scratch my head and then try doing what it asks by adding a (void) cast on the return…

(lldb) expr (void)[self.someDateFormatter setDateFormat:@"yyyy-MM-dd"]
<no result>

Sweet this didn’t error so let’s confirm it worked

(lldb) po [self.someDateFormatter dateFormat]
(id) $2 = 0x06a88430 yyyy-MM-dd

Now let’s try it out on our startDate

(lldb) po [self.someDateFormatter dateFromString:startDate]
(id) $7 = 0x06d7d130 2012-09-15 00:00:00 +0000

Excellent, jobs a gooden.

###More awkward calls

You’ll find that you actually need to cast a lot so just be very aware of that.

Here’s a couple examples of that

(lldb) p [self.view bounds]
error: no known method '-bounds'; cast the message send to the method's return type
error: 1 errors parsing expression

(lldb) p (CGRect)[self.view bounds]
(CGRect) $9 = origin=(x=0, y=0) size=(width=320, height=460)

(lldb) expr (void)[self.view setBackgroundColor:[UIColor redColor]]
error: no known method '+redColor'; cast the message send to the method's return type
error: 1 errors parsing expression

(lldb) expr (void)[self.view setBackgroundColor:(UIColor *)[UIColor redColor]]
<no result>
(lldb) expr (void)[self.view setBackgroundColor:(id)[UIColor redColor]]
<no result>

##Experimentation

Now I have no idea if this is useful/safe but you can actually mess around fairly freeform

I’ll start off by making a command alias to run the runloop

(lldb) command alias runloop expr (void)[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:(NSDate *)[NSDate date]]

Now calling runloop should spin the runloop once for me resulting in a screen update

Now let’s have a real play:

Without rebuilding - I want to create a label, change some settings and then finally give it some text.

####1. I need to get a frame:

(lldb) expr (CGRect)NSRectFromString(@"60 100 200 100")
(CGRect) $1 = origin=(x=60, y=100) size=(width=200, height=100)

####2. Now I need a label, with that frame

(lldb) po (id)[[UILabel alloc] initWithFrame:(CGRect)$1]
(id) $2 = 0x06b533a0 <UILabel: 0x6b533a0; frame = (60 100; 200 100); clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x6b46af0>>

####3. Let’s change the background colour to black

(lldb) expr (void)[(id)$2 setBackgroundColor:(id)[UIColor blackColor]]
<no result>

####4. Let’s make sure the text is readable by setting it’s colour to white

(lldb) expr (void)[(id)$2 setTextColor:(id)[UIColor whiteColor]]
<no result>

####5. Let’s add this to the view hierarchy

(lldb) expr (void)[self.view addSubview:(id)$2]
<no result>

####6. Now I’ll spin the runloop to check my handy work

(lldb) runloop
<no result>

Attempt 1

####7. Ooops let’s add some text and spin it again

(lldb) expr (void)[$2 setText:@"Awesome"]
<no result>
(lldb) runloop
<no result>

Attempt 2

Now I actually have a label on the screen with my text in it, without leaving the debugger.

##Conclusion

The examples provided here are fairly contrived, but the take away is that if you get familiar with the debugger you can actually do some cool experimentation. Here I’ve shown how to do some basic interrogation of objects without adding NSLog()’s and rebuilding, which is pretty cool. I’ve certainly had occasions where I’ve had a designer stood over my shoulder to tweak some UI and I would have loved to not have to rebuild repeatedly while we both wait just to check that the pixel adjustments were correct, especially when the view being edited was deep in a navigation stack and required a lot of clicking.

Polishing turds

There’s the old adage “You can’t polish a turd”, which just sounds like a challenge to me (this was of course proved wrong by the Mythbusters).

If I see some particularly unsightly code I’ll either fix it there and then or if it’s a tricky one I’ll make a note to stew on it and come back for a fix.

The aim of this post is not to point and make fun of some code but to examine what kind of steps can be taken to polish a fresh small dung, before it’s start to rot and make a real mess in your code base.

#Starting point

Here is todays example from a real project, the participants will not be named to save their blushes (technically I have done work on this project but Git blame has gotten me off the hook for this snippet).

UITextField *textField = (UITextField *)[self.scrollView viewWithTag:kATag]; textField.text = @"A"; textField.backgroundColor = kWhiteColor;
textField = (UITextField *)[self.scrollView viewWithTag:kBTag]; textField.text = @"B"; textField.backgroundColor = kWhiteColor;
textField = (UITextField *)[self.scrollView viewWithTag:kCTag]; textField.text = @"C"; textField.backgroundColor = kWhiteColor;
textField = (UITextField *)[self.scrollView viewWithTag:kDTag]; textField.text = @"D"; textField.backgroundColor = kWhiteColor;
textField = (UITextField *)[self.scrollView viewWithTag:kETag]; textField.text = @"E"; textField.backgroundColor = kWhiteColor;

The code essentially fills out some text boxes and then changes their background colour to indicate that they are filled out. Currently there are multiple statements per line and there is a lot of repetition.

There are many angles I can come at this dung with my polishing cloth but here is how I actually did tackle it.

#Step 1

The first change I would like to make is to lie to the compiler (just a little bit). The method -[UIView viewWithTag:] has a return type of UIView *, which means to stop the compiler moaning in this case the return value has to be cast to a UITextField *. By casting the value I am essentially saying

“Hey compiler I know you are really clever and all but on this occasion I know better and I’m telling you this is going to be a UITextField *

(it’s perfectly normal to have a conversation with the compiler whilst you code right?).

So I start to think - seems as I am already stepping in and telling the compiler that I know better, why not go the whole way and save some pixels by using id instead of UITextField *. That saves me some space and asterisks (which tend to draw my attention for no reason) and looks like this

UITextField *textField = (id)[self.scrollView viewWithTag:kATag]; textField.text = @"A"; textField.backgroundColor = kWhiteColor;
textField = (id)[self.scrollView viewWithTag:kBTag]; textField.text = @"B"; textField.backgroundColor = kWhiteColor;
textField = (id)[self.scrollView viewWithTag:kCTag]; textField.text = @"C"; textField.backgroundColor = kWhiteColor;
textField = (id)[self.scrollView viewWithTag:kDTag]; textField.text = @"D"; textField.backgroundColor = kWhiteColor;
textField = (id)[self.scrollView viewWithTag:kETag]; textField.text = @"E"; textField.backgroundColor = kWhiteColor;

#Step 2

The next thing I want to get rid of is the kWhiteColor. It’s name is too specific and I don’t like the use of #define to make it. This colour is also used throughout the project so I want it to be globally accessible and easy to change in one place. For this I’ll use a category.

I make sure to prefix the method to avoid collisions and in the process I have given the method a more appropriate name for what the colour actually represents in the problem domain as opposed to it’s actual colour.

UIColor+AppStyling.h

@interface UIColor (AppStyling)

+ (UIColor *)ps_completedFieldBackgroundColor;

@end

UIColor+AppStyling.m

#import "UIColor+AppStyling.h"

@implementation UIColor (AppStyling)

+ (UIColor *)ps_completedFieldBackgroundColor;
{
  return [UIColor whiteColor];
}

@end

I now need to import this anywhere it is needed - I’ll just make it available throughout my project by importing it into my pre compiled header.

Prefix.pch

...

#ifdef __OBJC__
    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    #import "UIColor+AppStyling.h"
#endif

...

As a result of this change the code is now slightly longer again as the old kWhiteColor is much shorted than the new [UIColor ps_completedFieldBackgroundColor]. I can live with this for now as I’ve gotten rid of the #define, given the colour a more appropriate domain specific name and made it into a normal method. This is how we stand now:

UITextField *textField = (id)[self.scrollView viewWithTag:kATag]; textField.text = @"A"; textField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];
textField = (id)[self.scrollView viewWithTag:kBTag]; textField.text = @"B"; textField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];
textField = (id)[self.scrollView viewWithTag:kCTag]; textField.text = @"C"; textField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];
textField = (id)[self.scrollView viewWithTag:kDTag]; textField.text = @"D"; textField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];
textField = (id)[self.scrollView viewWithTag:kETag]; textField.text = @"E"; textField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];

#Step 3

The next thing I want to tackle is the tags. I’m not fond of tags especially when you have to maintain them in two places (code and xibs - I’d quite like to see some imaginary construct like IBConstant which makes a constant available in IB, but that still wouldn’t help the problem much).

These views are in fact created in a xib so it’s a simple case of making some outlets and hooking them up.

@property (nonatomic, weak) IBOutlet UITextField *aTextField;
@property (nonatomic, weak) IBOutlet UITextField *bTextField;
@property (nonatomic, weak) IBOutlet UITextField *cTextField;
@property (nonatomic, weak) IBOutlet UITextField *dTextField;
@property (nonatomic, weak) IBOutlet UITextField *eTextField;

And with that the code can now be simplified to something like this

self.aTextField.text = @"A"; self.aTextField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];
self.bTextField.text = @"B"; self.bTextField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];
self.cTextField.text = @"C"; self.cTextField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];
self.dTextField.text = @"D"; self.dTextField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];
self.eTextField.text = @"E"; self.eTextField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];

Notes

  • The textFields are not actually named like this in the real project this is for demonstration purposes.
  • I only take a weak pointer as the containing view owns the textFields not my class.
  • Hindsight is always 20/20 and I could have skipped step 1 and come straight here but it’s better to take baby steps than to try and get clever.

#Step 4

There is a lot of repeated work with the setting of the textFields background colour, so I’ll DRY this up next using the nice new literal array syntax

self.aTextField.text = @"A"; 
self.bTextField.text = @"B"; 
self.cTextField.text = @"C"; 
self.dTextField.text = @"D"; 
self.eTextField.text = @"E"; 

for (UITextField *textField in @[ self.aTextField, self.bTextField, self.cTextField, self.dTextField, self.eTextField]) {
  textField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];
}

I’m liking the way the code is taking shape and looking less like a spreadsheet of repeated rows (cough cough ignore lines 1 .. 5).

#Step 5

This is still not as DRY as I would like as the textField ivars are mentioned twice. To solve this I can take a slightly different tactic and make an intermediary mapping. Annoyingly UIView does not conform to NSCopying so it can not be used as a key in a dictionary but I can make do with the slightly backward mapping of using the word first. The final result is something like:

NSDictionary *textToFieldMappings = @{
  @"A" : self.aTextField,
  @"B" : self.bTextField,
  @"C" : self.cTextField,
  @"D" : self.dTextField,
  @"E" : self.eTextField,
};

[textToFieldMappings enumerateKeysAndObjectsUsingBlock:^(NSString *text, UITextField *textField, BOOL *stop) {
  textField.text            = text;
  textField.backgroundColor = [UIColor ps_completedFieldBackgroundColor];
}];

#Conclusion

By going step by step I’ve managed to (IMHO) clean up this snippet. I have taken a dense block off code that reused the same local variable over and over to perform multiple tasks per line and elegantly split it up into a mapping step followed by an action step. I’ve used a category so that I can use language appropriate to the problem in a normal way and I’ve made the code much DRY’r and hopefully easier to maintain.

This code takes up more vertical space than the original (it wouldn’t if the original was broken down to one statement per line) and has some new files for the category, but it’s much more self descriptive and does not repeat it’s self at any point.

I can now put my polishing cloth away and keep my eyes peeled for the next turd.

Simplify the simple

Simple things should be simple. That’s easier said than done in a language like Objective-C. Sometimes things that are in fact simple look difficult just because of the syntax.

##Problem

I often prefer to override my getters to lazy load objects the moment they are actually required as opposed to setting up everything in init* methods. This also cleans up any init* methods by removing a chunk of boiler plate nothingness. This can get a bit hairy, consider (read: skim) the following example - the content here is really not important

- (NSCalendar *)calendar;
{
  if (!_calendar) {
    _calendar = [NSCalendar currentCalendar];
  }
  return _calendar;
}

- (NSTimeZone *)timeZone;
{
  if (!_timeZone) {
    _timeZone = [[NSTimeZone alloc] initWithName:@"GMT"];
  }
  return _timeZone;
}

- (NSDate *)minimumDate;
{
  if (!_minimumDate) {
    _minimumDate = [[NSDate alloc] initWithTimeIntervalSince1970:0];
  }
  return _minimumDate;
}

- (NSDate *)maximumDate;
{
  if (!_maximumDate) {
    _maximumDate = [[NSDate alloc] initWithTimeIntervalSince1970:MAXFLOAT];
  }
  return _maximumDate;
}

The above code looks like it is doing more than it actually is because of the if statements and all of the vertical space it consumes. This kind of code generally causes me to do a quick double take to skim the code to make sure it really is only lazy loading objects. When I have to do a double take it generally means I will make a mistake at some point later on so I prefer to avoid them if at all possible. It is also quite likely that a double take can knock me off my train of thought by taking unnecessary detours - I can only hold so much in my brain at once.

##Solution

I tend to hide this all at the bottom of a class below a #pragma mark - Properties. That’s enough to flip the bit in my head that says expect this kind of boiler plate code.

##Is that enough?

I don’t think it is, the code is still big bulky and annoying to look at. Granted I could not be so stubborn and transform the if statements into one liners but that would break my coding conventions and cause more double takes. I like to keep my if statements consistent and always use curly braces to avoid any pain later on. This also helps readability as things are always how I expect them to be. If something can be more succinctly written with ternary syntax then I will favour that - if not it’s multi-line, curly brace goodness for me.

##Experimentation

So the current solution I am experimenting with on these simple cases is to use the ternary syntax to make the simple getters as simple as possible. With this the above is transformed into the slightly more compact and easy to read

- (NSCalendar *)calendar;
{
  return _calendar = _calendar ?: [NSCalendar currentCalendar];
}

- (NSTimeZone *)timeZone;
{
  return _timeZone = _timeZone ?: [[NSTimeZone alloc] initWithName:@"GMT"];
}

- (NSDate *)minimumDate;
{
  return _minimumDate = _minimumDate ?: [[NSDate alloc] initWithTimeIntervalSince1970:0];
}

- (NSDate *)maximumDate;
{
  return _maximumDate = _maximumDate ?: [[NSDate alloc] initWithTimeIntervalSince1970:MAXFLOAT];
}

The syntax seems like a familiar old friend for a Ruby fan and is pretty concise without much compromise. I have even managed to put this class on a diet and trim 12 lines in just this simple example. (Here’s the Ruby example)

def minimum_date
  @minimum_date ||= NSDate.alloc.initWithTimeIntervalSince1970 0
end

This doesn’t help me in cases where I want to lazy load and configure an object at the same time, but my goal here is to make simple things simple. Returning a simple object is pretty simple but configuring one is not. For objects that need configuration I can go back to the warmth of those cosy curly braces, I also get the added advantage of being able to determine which methods return simple objects and which methods do a little more heavy lifting with just a glance.

// Object instantiated and needs some additional configuration
- (NSDateFormatter *)dateFormatter;
{
  if (!_dateFormatter) {
    _dateFormatter = [[NSDateFormatter alloc] init];
    _dateFormatter.dateFormat = @"yyyy-mm-DD";
  }
  return _dateFormatter;
}

// Simple object instantiated and returned
- (NSCalendar *)calendar;
{
  return _calendar = _calendar ?: [NSCalendar currentCalendar];
}

Here I can push the simple getter further down the class to emphasise even more it’s status in the class.

##Conclusion

I am still only really toying with this syntax but I currently like the additional semantic information I can get by just glancing at the code. I can quickly see which getters lazy load a simple default value and which getters lazy load objects and involve a little more setup work. I can imagine that this syntax may present an initial double take to anyone who was working on my code base and had never come across this before but it has a considerably lower barrier to entry than design patterns that are employed all of the time in large projects.