Mysterious Trousers

Quality software and amazing support since 2010

We’re a small team dedicated to making you happy. We achieve this through synergizing analytics and best-of-breed social blah blah blah hard work and honest-to-goodness customer service.

Filtering by Author: Parker Wightman

Extend not a library more than you are able.

When shipping apps, especially those that deal with CoreData or otherwise keep track of data, you often need to normalize that data or somehow make a correction if things become inconsistent. This often comes at app update time, and it’s usually a block of code you want to run once and only once. For each app I build I end up writing some custom logic to handle it. Today I decided to wrap that logic into a library called MTMigration, available on GitHub. The API looks something like this:

[MTMigration migrateToVersion:@"1.1" block:^{
    [obj doSomeDataStuff];
}];

However, the point of this post is to explain that the API I decided upon varies a bit from my original attempts. It looked like this:

[MTMigration migrateToVersion:@"1.1" 
                      options:MTMigrationOptionOnFreshInstall | MTMigrationOptionOnUpdate
                        block:^{
                            [obj doSomeDataStuff];
                        }];

and this:

[MTMigration migrateToVersion:@"1.1" 
              ifMigratingFrom:@"1.0"
                        block:^{
                            [obj doSomeDataStuff];
                        }];

Though I’d already identified a real-world problem that needed solving, namely allowing a block of code to run once on an update, I began imagining all the different scenarios MTMigration might also cover. “You might want to only run the block if you’re updating, or if you’re on a fresh install!” I pontificated, “Or maybe you only want to run it if you are upgrading from a specific version!” said I.

I quickly realized that I was no longer solving a problem I actually had. As I began thinking about the implementation details, it became clear I had no real use-case to test my bright ideas on, and it began to get messy. So I scrapped it.

This principle extends to all aspects of building a library. None of the APIs I had debated about are “bad” or “wrong” in any way, I’m just not in a position to implement it. I have no real-world use for them, so I’d likely do it wrong. I really hope someone comes along that is having those exact problems, as they’ll make a killer extension to MTMigration, with the experience to back it up.

I’d encourage all developers to keep this in mind next time you’re writing a library. Are you trying to solve problems you actually have, or at least have had before? If not, consider dropping the feature. Add it when you do have the problem, or if it’s open source, let someone else take a crack at it that’s actually experiencing the problem. If no one is actually experiencing the problem, well, there’s your answer.

Zeus

Zues is a really cool gem that preloads your Rails environment so commands like rails console, rails server, rails generate, etc. boot in less than a second. Works as advertised. All sorts of awesome.

RVM, my love, I must leave thee. And faster Ruby too!

I’ve been in a very passionate relationship with RVM, as have many others (it gets around, see) and I’ve seen a growing interest in a more attractive, “modest is hottest” alternative called rbenv. I thought they were fools at first, RVM has been nothing but pure joy for me. Until…

See, RVM fit two awesome needs: gemsets and managed ruby versions. Gemsets allowed me to stay away from the dreaded bundle exec preceeding my every command, as well as “blah blah gem version blah has already been activated!” errors. But gemsets also cause you to re-download every gem for every project, which began to wear on me. It was slow, and eating into my GB’s. But, it turns out the the bundle exec thing has been solved and with that, it’s a no brainer. I dumped RVM and rbenv is my new best friend. Fair-weather friend, indeed. Much lighter-weight and they tell me it’s safer for some reason, which I blindly accept.

I view this also from a teaching perspective. I run a Ruby on Rails student group at the University of Utah and teaching RVM, and in particular gemsets, is a friggin’ nightmare for beginners. rbenv + rbenv-bundler is a much cleaner option that is less likely to catch up beginners and experts alike. Set it and forget it! (I love that this video is a youtube video of a youtube video.)

As an aside, I found this really cool gist that installs a souped-up version of Ruby that runs about 30% faster. Again, that time adds up with how slow Rails is these days. I found my speed-up to be consistent with that gist. A win-win.

psst... it's a FatSecret

We’re working on a new app, as some of you may know, and it’s required we find some sort of database to get food data from. Calories, protein, serving sizes, etc. We started with the USDA food database. This thing is a piece of garbage. Naming conventions are inconsistent and absurdly long, sometimes in ALL CAPS even. It was also missing several fairly common foods (coconut oil, anyone?). Not to mention it’s distributed as either a Microsoft Access database, an Excel sheet, or a custom file format. Really? Access or Excel? Those were immediately unusable to us, so we were left with the custom file format. This thing is a real piece of work, let me give you a taste:

~06075~^~SOUP,BF BROTH OR BOUILLON,PDR,DRY~^3.27^213 ^15.97^8.89^54.50^17.40^0.0^16.71^60^1.00^51^320^446^26000 ^0.00^0.000^0.459^27.6^0.0^0.070^0.243^4.467^0.300^0.200^32 ^0^32^32^113.4^1.00^0^0^0^0^0^0^0^0^2.17^0.0^0^3.2^4.320 ^3.616^0.332^10^3.6^~1 cube~^6.0^~1 packet~^0 ~06076~^~SOUP,BEEF BROTH,CUBED,DRY~^3.30^170 ^17.30^4.00^59.30^16.10^0.0^14.51^60^2.23^50^225^403^24000 ^0.21^0.000^0.386^27.6^0.0^0.200^0.240^3.300^0.300^0.200^32 ^0^32^32^113.4^1.00^1^0^0^0^0^0^0^0^0.00^0.0^0^0.0^1.990 ^1.670^0.160^4^3.6^~1 cube~^^~~^0

I spent a good many hours writing a custom parser for that beauty. Why in the world can’t they just do JSON, or I’d even get my big-boy pants on and suffer through some XML. We no longer live in an age when your best option is custom file formats! At the VERY least provide some sort of parser I can use. I… just… how…

So we decided to pivot. We did some searching and found FatSecret. It’s paid for the Premier tier (which we’ll probably end up having to get) but it also has a free plan. Hallelujah.

After determining that it was our best option, I unknowingly dove into the pits of OAuth hell. It authenticates with OAuth, which is fine, except there’s not fantastic iOS library support for OAuth. I did some searching and the best I could find was OAuthCore, which generates a signed header, but I needed it as a query string in a GET request. Wasn’t too tough, just switched a few lines of code, debugged it a good while, scratched my head, and suddenly it worked. I was moments away from giving up when light shown through the heavens and I was Enlightened. I got back some JSON of food. And it was very desirable. Consistent naming, hundreds of results, it was beautiful. I cried. Not really, I drank some Pomegranate 7-up and kissed my wife.

All there was left to do was abstract my code into an open source library. I’d give you a song-and-dance about MT’s commitment (read: burning passion) for open source (which is true) but it really, in this case, came down to how cool CocoaPods is that there’s really no reason not to open source something like this. Here it is, if you ever need it. I pray even my worst enemy won’t find that USDA database.

And that’s the Tale of FatSecretKit.

Blocks: A Case Against Protocol Delegation

Adam claimed the other day that in every situation he could think of, blocks could replace protocol delegation in Objective-C. I had never thought about this and almost dismissed it as soon as I heard it, but I’ve thought about it a lot the past few days. I wrote an experimental, drop-in replacement for UITableView called MTBlockTableView that demonstrates this idea. There’s 3 particular situtations where I use delegates the most, and I’d like to expand on each of them and the pros and cons of block versus protocol delegation.

UITableView

In MTBlockTableView, we took the typical delegate implementation and used blocks for each delegate method. Consider the difference from the snippets below:

Delegate Approach

// MyViewController.h

@interface MyViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

@property (strong, nonatomic) UITableView *tableView;

@end



// MyViewController.m

@implementation

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    ...
}

- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
}

@end

Blocks Approach

// MyViewController.h

@interface MyViewController : UIViewController // No need to conform to protocols

@property (strong, nonatomic) MTBlockTableView *tableView;

@end



// MyViewController.m

@implementation

- (void) viewDidLoad {
    [_tableView setNumberOfRowsInSectionBlock:^NSInteger(UITableView *tableView, NSInteger section) {
        ...
    }];
    
    [_tableView setCellForRowAtIndexPathBlock:^UITableViewCell *(UITableView *tableView, NSIndexPath *indexPath) {
        ...
    }];
}


@end

Behind-the-scenes, MTBlockTableView is its own delegate and data source and it simply calls the corresponding blocks for each of the delegate methods.

However, in this particular example where the view controller is the delegate of only a single UITableView, you kind of break even, if you ask me. They’re both pretty much the same in terms of lines of code, and it mostly comes down to taste. With blocks, there’s no conforming to protocols which can be nice, but you also don’t get the compiler-enforced @required/@optional protocol method niceties. But let’s take another example.

UIAlertView

Better uses for blocks can be found when you have multiple objects of the same type using the same object as their delegate. UIAlertView comes to mind, where just one works fine:

// MyViewController.m

@implementation MyViewController

- (void) askForFirstName {
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"First Name"
                                                        message:@"What is your first name?"
                                                       delegate:self
                                              cancelButtonTitle:@"Cancel"
                                              otherButtonTitles:@"OK", nil];
    
    alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
    
    [alertView show];
}

- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    [_networkManager submitFirstNameToServer:[alertView textFieldAtIndex:0].text]];
}

@end

But what if you have two alert views? You could create distinct objects, each to be separate delegates (WAY too much work for something as simple as UIAlertView ought to be), or you could rig up something like this:

// MyViewController.m

#define ALERT_VIEW_FIRST_NAME_TAG 0
#define ALERT_VIEW_LAST_NAME_TAG 1

@implementation MyViewController

- (void) askForFirstName {
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"First Name"
                                                        message:@"What is your first name?"
                                                       delegate:self
                                              cancelButtonTitle:@"Cancel"
                                              otherButtonTitles:@"OK", nil];
    
    alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
    alertView.tag = ALERT_VIEW_FIRST_NAME_TAG;
    
    [alertView show];
}

- (void) askForLastName {
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Last Name"
                                                        message:@"What is your last name?"
                                                       delegate:self
                                              cancelButtonTitle:@"Cancel"
                                              otherButtonTitles:@"OK", nil];
    
    alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
    alertView.tag = ALERT_VIEW_LAST_NAME_TAG;
    
    [alertView show];
}

- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (alertView.tag == ALERT_VIEW_FIRST_NAME_TAG) {
        [_networkManager submitFirstNameToServer:[alertView textFieldAtIndex:0].text]];
    } else if (alertView.tag == ALERT_VIEW_LAST_NAME_TAG) {
        [_networkManager submitLastNameToServer:[alertView textFieldAtIndex:0].text]];
    }

}

@end

But then you’re getting crazy. I don’t like to get crazy. Consider a block-based approach:

- (void) askForFirstName {
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"First Name"
                                                        message:@"What is your first name?"
                                                       delegate:self
                                              cancelButtonTitle:@"Cancel"
                                              otherButtonTitles:@"OK", nil];
    
    alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
    
    [alertView setClickedButtonAtIndexBlock: ^(UIAlertView *alertView, NSInteger buttonIndex) {
        [_networkManager submitFirstNameToServer:[alertView textFieldAtIndex:0].text]];
    }];
    
    [alertView show];
}

- (void) askForLastName {
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Last Name"
                                                        message:@"What is your last name?"
                                                       delegate:self
                                              cancelButtonTitle:@"Cancel"
                                              otherButtonTitles:@"OK", nil];
    
    alertView.alertViewStyle = UIAlertViewStylePlainTextInput;

    [alertView setClickedButtonAtIndexBlock: ^(UIAlertView *alertView, NSInteger buttonIndex) {
        [_networkManager submitLastNameToServer:[alertView textFieldAtIndex:0].text]];
    }];
    
    [alertView show];
}

Now each UIAlertView is in charge of calling its own, specific finished code, as it should be. Again, behind-the-scenes it’s just conforming to its own protocol and each delegate method is calling its corresponding block. This is an out-right win as far as I’m concerned. UIAlertViews are meant to be quick-and-easy, but that moment when you realize you have to conform to a protocol to respond to user action is always a brutal one, and having multiple alert views gives me hives. Fewer lines of code and ideas are grouped together logically.

I recently tried using RKClient, an HTTP request client, from the RestKit framework for an open source project and ran into this same problem. You tell the client to fetch JSON at some URL and it calls a delegate method when it’s done. What if you’re making multiple requests, and you want to handle the JSON differently for each request? You’re hosed. Delegates and protocols break down in this situation. I ended up using SVHTTPRequest instead, which uses blocks instead of delegates, and it’s really quite elegant.

(To be fair, I was using RKClient in an unorthodox way, I wasn’t using the object mapping that’s meant to be used with RestKit, which would have solved this particular problem, but you get the idea.)

This can also apply to our previous example where you might want one view controller to control two trivial table views. Rare, perhaps, but still a flexibility bonus that a block-based approach has over protocols.

One more example.

Modal View Controllers

Displaying modal view controllers usually goes something like this for me, where MySourceViewController presents MyDestinationViewController:

// MySourceViewController.h

#import "MyDestinationViewController.h"

@interface MySourceViewController : UIViewController 
@end

// MySourceViewController.m

#import "MySourceViewController.h"

@implementation MySourceViewController

- (IBAction)settingsButtonTapped:(id)sender {
    MyDestinationViewController *controller = [[MyDestinationViewController alloc] init];
    
    controller.delegate = self;

    [self presentModalViewController:controller animated:YES];
}

- (void) destinationViewControllerDidFinish:(MyDestinationViewController *)controller {
    [self dismissModalViewControllerAnimated:YES];
}

@end

// MyDestinationViewController.h

@protocol MyDestinationViewControllerDelegate;



@interface MyDestinationViewController : UIViewController

@property (nonatomic, weak) id delegate;

@end



@protocol MyDestinationViewControllerDelegate 

- (void) destinationViewControllerDidFinish:(MyDestinationViewController *)controller;

@end

// MyDestinationViewController.m

#import "MyDestinationViewController.h"

@implementation MyDestinationViewController

- (IBAction) doneButtonTapped:(id)sender {
    [_delegate destinationViewControllerDidFinish:self];
}

@end

Which is all fine and well, but in this situation you are still looking to do something quite simple. That’s a fair bit of code (declaring the protocol, conforming to it, etc) and blocks provide something a little more succinct:

// MySourceViewController.h

#import "MyDestinationViewController.h"

@interface MySourceViewController : UIViewController
@end

// MySourceViewController.m

#import "MySourceViewController.h"

@implementation MySourceViewController

- (IBAction)settingsButtonTapped:(id)sender {
    MyDestinationViewController *controller = [[MyDestinationViewController alloc] init];
    
    [controller setFinishedCallback:^(MyDestinationViewController *controller) {
        [self dismissModalViewControllerAnimated:YES];
    }];

    [self presentModalViewController:controller animated:YES];
}

@end

// MyDestinationViewController.h

@interface MyDestinationViewController : UIViewController

@property (nonatomic, strong) void (^finishedCallback)(MyDestinationViewController *controller);

@end

// MyDestinationViewController.m

#import "MyDestinationViewController.h"

@implementation MyDestinationViewController

- (IBAction) doneButtonTapped:(id)sender {
    if (_finishedCallback) {
        _finishedCallback(self);
    }
}

@end

Again, a huge win. No need to define a protocol, or conform to it. You handle both the presenting and the dismissal all at once. It’s much more elegant, natural, and pleasurable to code this way (once you get over the ugly block syntax), having written code using this convention for about a week now.

Adam and I feel this is the next natural progression of the delegate design pattern. Protocols were created because smart guys with beards realized that in certain circumstances, objects didn’t need to know what type another object was, just that it implemented certain methods. This was (and still is to an extent) very expressive, and is a key feature of why UIKit trumps many other graphical frameworks. But even that is overkill sometimes. In the last two situations I discussed above, the object doesn’t even need to know about the object at all, just that it can call a method.

We’re not saying do away with delegates altogether since in certain situations, like with UITableView, blocks are not an all-out win (though what if you wanted one view controller to control two table views?). But we are saying some of the UIKit framework, such as UIAlertView, would be much more elegant and expressive if we could use blocks in place of delegates. What do you think? Let us know at @mystrou on Twitter.

© 2013 Mysterious Trousers, LLC. All Rights Reserved. Background photo by hsld