Blog

    Cocoa Coding Style Enforcement

    December 30, 2013

    Some time back, the New York Times's iOS team published Objectively Stylish, an Objective-C style guide. You've probably worked on a project before where every team member has their own unique coding style. While one can argue the relative merits of various stylistic choices, it's hard to argue against having a uniform style. For this reason, most projects should just pick a style and stick with it. But how can you make sure your chosen coding style is being maintained? Through the use of several common open source tools, you can easily enforce your project's coding style.

    The main tool that all of this revolves around is Uncrustify. Uncrustify is a highly customizable code beautifier for C-like languages. Being primarily a command line utility, the easiest way to install and integrate Uncrustify into Xcode is to install the BBUncrustifyPlugin-Xcode plugin. You can download the latest release as a zip file here. After downloading and unzipping the plugin, simply move UncrustifyPlugin.xcplugin into ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins and restart Xcode.

    After restarting Xcode you should notice several new options in the Edit menu:

    Xcode edit menu

    These new options should be fairly self explanatory. They allow you to beautify code with various degrees of scope within Xcode. BBUncrustifyPlugin-Xcode comes with a default set of style standards. If you want to customize these standards you can either go digging in Uncrustify’s configuration file or you can use UncrustifyX’s easy-to-use graphical user interface.

    Customizing Your Style

    UncrustifyX can act as a standalone graphical interface to beautify your code, but its ability to easily customize Uncrustify’s configuration file is of greater interest to us. You can download the latest UncrustifyX release here. After unzipping UncrustifyX and moving UncrustifyX.app to /Applications you will get a fourth new option added to Xcode’s Edit menu:

    Xcode edit menu

    Pick this option and you should be presented with a modal telling you that a custom configuration was not found and giving you the option to create one. Proceeding will copy the bundled Uncrustify configuration file to ~/.uncrustifyconfig and open it in UncrustifyX for customization. Let’s compare some of the recommendations from the NYTimes Objective-C Style Guide to the options provided in UncrustifyX. First, let's take a look at what they have to say about spacing.

    • Indent using 4 spaces. Never indent with tabs. Be sure to set this preference in Xcode.
    • Method braces and other braces (if/else/switch/while etc.) always open on the same line as the statement but close on a new line.

    For example:

    if (user.isHappy) {
    //Do something
    }
    else {
    //Do something else
    }

    Indent using 4 spaces can be set by selecting Indent with tabs to 0 meaning “spaces only”. You’ll also notice that UncrustifyX has a built-in documentation viewer. You can click the “i” button next to each option to read what it does and what its valid values are.

    The default brace style configuration included with BBUncrustifyPlugin-Xcode should already match the style guide. If you’re interested how this is accomplished the following options are set to “Remove”:

    • Newline between function signature and open brace
    • Newline between if and open brace
    • Newline between else and open brace
    • Newline between else if and open brace
    • Newline between while and open brace
    • Newline between switch and open brace

    You can switch your brace indent style to Allman style by changing all of the preceding options to “Add”. Now we'll take a look at the style guide's recommendations for conditionals.

    Conditional bodies should always use braces even when a conditional body could be written without braces (e.g., it is one line only) to prevent errors. These errors include adding a second line and expecting it to be part of the if-statement. Another, even more dangerous defect may happen where the line "inside" the if-statement is commented out, and the next line unwittingly becomes part of the if-statement. In addition, this style is more consistent with all other conditionals, and therefore more easily scannable.

    For example:

    if (!error) {
        return success;
    }

    Not:

    if (!error)
        return success;

    or

    if (!error) return success;

    You can force braces to be added for single line statements by setting the following options to "Add":

    • Braces on single-line do statement
    • Braces on single-line else statement
    • Braces on single-line for statement
    • Braces on single-line while statement

    What no if statement? As of the time of this writing, there is a mislabeling in UncrustifyX. The option labeled "Braces on single-line else statement" also covers if statements.

    When you're happy with your rules, you can save them by choosing "Export". You should save your configuration file to .uncrustifyconfig in your home directory. OS X will warn you that the file will be hidden because of the dot but you can safely click "Use '.'" to save anyway.

    Enforcement

    What we have so far is a code beautifier with some customized rules. This is great, but our real end goal is to make sure that code is never commited which violates these rules. For the enforcement of our rules, we will employ the use of git hooks. GitHub user David Martin has already done the hard work for us of creating a pre-commit-script that does exactly what we want located here. Save the file at the path .git/hooks/pre-commit in the git repository you want to add style enforcement to. Open the pre-commit script you just saved in an editor, because you'll need to modify the following variables from the settings section.

    Setting Value
    UNCRUSTIFY "/Applications/UncrustifyX.app/Contents/Resources/uncrustify"
    CONFIG "$HOME/.uncrustifyconfig"
    SOURCE_LANGUAGE "OC"
    FILE_EXTS ".c .h .cpp .hpp .m .mm"

    You can use the uncrustify binary that comes with UncrustifyX assuming you copied UncrustifyX to /Applications. You can also easily install a standalone uncrustify executable using Homebrew by executing:

    $ brew install uncrustify

    In which case, you'll want to set UNCRUSTIFY to /usr/local/bin/uncrustify. You will also want to make sure your script is executable by executing:

    $ chmod 755 .git/hooks/pre-commit

    The script has a dependency on another script called canonicalize_filename.sh which you can download here. Copy canonicalize_filename.sh into .git/hooks/canonicalize_filename.sh and set its permissions to executable as well.

    $ chmod 755 .git/hooks/canonicalize_filename.sh

    Now that everything is in place, we're ready to break some rules and hope to get caught. I'll try to commit the following simple test.m file which violates the style standards we set above.

    #import <Foundation/Foundation.h>
    
    int main(int argc, char *argv[]) {
        @autoreleasepool {
            NSUInteger i = 1;
    
            if (i < 1)
                NSLog(@"Hello");
    
            if (i < 2)
            {
                NSLog(@"World");
            }
        }
    }

    When attempting to commit, you should get an error similar to what follows.

    $ git add test.m 
    $ git commit -m 'Test commit'
    Parsing: test.m as language OC
    
    The following differences were found between the code to commit and the uncrustify rules:
    
    --- a/test.m    2013-12-29 04:01:46.000000000 -0500
    +++ b/test.m    2013-12-29 04:24:42.000000000 -0500
    @@ -1,15 +1,15 @@
     #import <Foundation/Foundation.h>
    
     int main(int argc, char *argv[]) {
    -    @autoreleasepool {
    -        NSUInteger i = 1;
    -        
    -        if (i < 1)
    -            NSLog(@"Hello");
    -        
    -        if (i < 2)
    -        {
    -            NSLog(@"World");
    -        }
    -    }
    +   @autoreleasepool {
    +       NSUInteger i = 1;
    +
    +       if (i < 1) {
    +           NSLog(@"Hello");
    +       }
    +
    +       if (i < 2) {
    +           NSLog(@"World");
    +       }
    +   }
     }
    
    You can apply these changes with:
     git apply /tmp/pre-commit-uncrustify-1388309082.patch
    (may need to be called from the root directory of your repository)
    Aborting commit. Apply changes and commit again or skip checking with --no-verify (not recommended).
    $

    This pre-commit script is very helpful in that it generates patch files to make the necessary changes for you. In this case, I can follow the error's recommendation and apply the patch.

    $ git apply /tmp/pre-commit-uncrustify-1388309082.patch

    Your patch file will have a different random filename so just refer to the error output. After applying the patch you should be able to inspect the test.m file and see that it has been beautified and now conforms to the style rules.

    #import <Foundation/Foundation.h>
    
    int main(int argc, char *argv[]) {
        @autoreleasepool {
            NSUInteger i = 1;
    
            if (i < 1) {
                NSLog(@"Hello");
            }
    
            if (i < 2) {
                NSLog(@"World");
            }
        }
    }

    After applying the patch, you should now be able to commit to the repository without an error. Congratulations, your style is now being enforced in your local git repository. If you want to enforce the style on a shared git repository, you can follow the exact same procedure, except instead of naming your git hook script .git/hooks/pre-commit, you'll name it .git/hooks/pre-push and it will be located on the remote server instead of your local repository. In this scenario, you'll be able to commit style violations, but the server will not accept them being pushed to it.

    Internet Plus

    November 5, 2013

    HBO Go Logo

    An article has been circulating around the internet recently which describes a mythical cord cutter's dream package, an internet only package which also includes access to HBO Go. Normally to use HBO Go you have to have a cable plan, but this plan promises streaming access to HBO for the same price as an internet only plan. If you read the fine print it's actually an extremely basic cable plan which also includes HBO which is masquerading as a cord-cutter plan, but who cares if the price is right.

    The other fine print on this is that it's an experiment only available in some markets. I'm happy to report that I am in one of those markets and it is awesome. The plan was not listed on the Comcast website. I had to call twice and talk to different people describing the plan in different ways (e.g., by price, speed, etc). They finally found it and it ended up costing me $5 extra per month to get streaming access to HBO.

    There are other response articles circulating about how this is not what it seems because the price listed is an introductory price for new customers, but isn't that how every cable plan is? The bottom line is, in my market it's $39.99 if you're a new customer, $69.99 if you're not, you get 25Mbps internet, access to HBO Go, and access to Comcast's Streampix service. HBO Go is viewable from many devices including Apple TV, Roku, iPhones, iPad, Android devices, and of course desktop computers.

    RIP Google Reader, Long Live Feed Wrangler

    March 19, 2013

    Google Reader Logo

    I've been a longtime user of Google Reader. To back up even further, I've been an even longer time user of RSS. The news of Google deciding to shutdown Reader was a big disappointment to me. Now admittedly, Google Reader is a niche product that Google never quite figured out how to fully monetize, but most of what Google does is a little vague on the monetization details. Google has been shutting down a lot of products, but this should probably be seen more as a sign that they are growing up and learning to focus their efforts. I still haven't quite figured out what Google Glass says about them, but I can't help think Adam Lisagor is onto something when he called it a Segway for your face.

    After hearing the news that David Smith has been working on a Google Reader replacement, I've decided to put aside my disappointment and see Reader's demise as an exciting opportunity to shake things up in the world of RSS aggregation. The one thing I don't want to be, is the one guy still using Eudora) while everyone else has moved on to better things. Although the details are pretty sparse, I'm still excited about Smith's Feed Wrangler. The reason I'm excited about it is that Smith hit all the right notes in his explanation of why he decided to create an RSS aggregator on his podcast Developing Perspective.

    I use Reader almost strictly as a syncing back-end. There are other projects which will seek to recreate Reader's syncing API, but this is probably the wrong approach since it was never intended to be a public API. There are a lot of good apps that interface with Google Reader and I change clients every few months. Smith has said that he'll launch Feed Wrangler with clients for iOS and OS X and will make an API available for 3rd party clients. This exactly matches the way I currently use Google Reader.

    The problem with most traditional RSS readers is they treat RSS like email. What I want from RSS is the ability to aggregate a large number of sources, not miss anything important, but not have to take an action for every single story that appears in a feed. The biggest mistake that most RSS readers make is to use an unread count badge. There is a lot of interesting stuff going on in the space of reformatting RSS content to look more magazine-like. Flipboard gets a lot of stuff right, but isn't in itself a sync framework.

    Taking a cue from App.net, Feed Wrangler will explore a fresh new monetization concept called actually paying for stuff on the internet. In general, I agree with the concept that "if you're not paying for the product, you are the product." This is certainly true in the case of Facebook. We'll have to see exactly what the pricing is like for final judgment. App.net eventually went to a freemium model, which I believe works well for software products with a social component.

    There are of course a lot of other alternatives to Google Reader which already exist and are popping up to fill the void so it's probably still too early to call a winner. So how will I read my feeds in the meantime? I'm using Google Reader because it isn't July 1st yet! Also, did you know they open-sourced Eudora?

    Generating Spritesheets with Grunt and Spritesmith

    February 20, 2013

    CSS Sprites can greatly increase the loading speed of web sites, by reducing the number of HTTP requests. Multiple images are combined into a single image and individual image regions are defined using a stylesheet. Creating spritesheets manually can be a long a tedious process. There are a number of tools one can use to assist with creating sprites, but wouldn't it be better if it were just part of the build process? It is now possible to do just that using Grunt and Spritesmith. I'll walk you through setting it up.

    Grunt is a build process automation tool for web projects. It's like using Make), but the rules and tasks are defined in JavaScript. Grunt is built on top of Node.js, but your project doesn't need to have any server-side scripting to use it. In fact, it really doesn't need to be a web-based project at all, but most of the built-in tasks and plug-ins are of course geared towards web projects.

    If you are not already using Node.js, you'll need to install it using the installer provided on nodejs.org. When you have Node.js set up and working, you'll want to install Grunt globally. This is quite easy using NPM. You can install Grunt using the following command. You will most likely need to use sudo to elevate your privileges and install Grunt globally.

    npm install -g grunt-cli

    After installing the Grunt command-line interface, you should be able to run the Grunt executable by typing grunt. If you can't, then there's a problem with your PATH. Check to see that /usr/local/bin is in your PATH.

    $ grunt
    grunt-cli: The grunt command line interface. (v0.1.6)
    
    Fatal error: Unable to find local grunt.
    
    If you're seeing this message, either a Gruntfile wasn't found or grunt
    hasn't been installed locally to your project. For more information about
    installing and configuring grunt, please see the Getting Started guide:
    
    http://gruntjs.com/getting-started

    If you successfully run the Grunt executable, you should see it complain that it can't find a Gruntfile. That's because we have not made one yet. A Gruntfile is the Grunt equivalent of a Makefile, if you are familiar with Make. We'll start out by creating a sprite task, by creating a file called Gruntfile.js in the root folder of our project.

    module.exports = function(grunt) {
        grunt.initConfig({
            sprite: {
                dist: {
                    src: ['sprites/*.png'],
                    destImg: 'public/images/sprite.png',
                    destCSS: 'less/sprite.less',
                    cssFormat: 'less',
                    imgPath: '../images/sprite.png',
                    algorithm: 'left-right'
                }
            }
        });
    
        grunt.loadNpmTasks('grunt-spritesmith');
        grunt.registerTask('default', 'sprite');
    };

    Here's what those properties mean.

    Property Meaning
    src The images to combine.
    destImg The name of the combined image.
    destCSS The stylesheet to create.
    cssFormat The format of the stylesheet to output.
    imgPath The path of the combined image to use in the stylesheet.
    algorithm How to organize the resultant image.

    Note that I'm also using the LESS stylesheet language because it will also allow us to efficiently combine the styles created by Spritesmith with our own styles. We now need to add Spritesmith and LESS as dependencies. Modify or create your package.json file to include grunt-spritesmith and grunt-contrib-less as devDependencies.

    {
        "name": "spritesmith-example",
        "version": "0.0.1",
        "private": true,
        "devDependencies": {
            "grunt": "~0.4.0",
            "grunt-spritesmith": "~0.5.2",
            "grunt-contrib-less": "~0.5.0"
        }
    }

    Spritesmith also requires that you install either Cairo or Graphics Magick. For this tutorial, I'll install Cairo via the Homebrew ports system on OS X.

    $ brew install cairo

    After installing Cairo or Graphics Magick, you can install your grunt-spritesmith and grunt-contrib-less dependencies by executing the following command in the project root.

    npm install

    Now you need to add some images to create your spritesheet. For the purposes of this demonstration, I will use the following 3 images. You can download them here. If you're following along you should unzip the file and put the 3 images in the sprites folder we specified in Gruntfile.js.

    You should now be able to generate your spritesheet by executing the grunt command in the root folder of your project.

    $ grunt
    Running "sprite:dist" (sprite) task
    
    Done, without errors.

    If you open the generated file public/images/sprite.png, you should see something that looks like the following image.

    The 3 source images have been combined into a single resultant image. You should also find a LESS stylesheet located at less/sprite.less which describes the properties of the images.

    Now that you've created your spritesheet, we need to use it. Create a new LESS spreadsheet located at less/sprite.less that looks like this.

    @import "sprite.less";
    
    .kiwi-image {
        .sprite(@image1);
    }
    
    .windmill-image {
        .sprite(@image2);
    }
    
    .tree-image {
        .sprite(@image3);
    }

    This file imports the generated sprite.less stylesheet and then defines 3 styles that use them. Notice that Spritesmith has created styles that match your image filenames, so you probably want to give your images more meaningful filenames than image1.png, image2.png, and image3.png like we did in this tutorial. It should also be noted that you can put your other site related styles in this file or create other LESS stylesheets and import them here.

    You now need to update Gruntfile.js to compile your LESS stylesheet. You should load and configure the grunt-contrib-less task resulting in the following file.

    module.exports = function(grunt) {
        grunt.initConfig({
            sprite: {
                dist: {
                    src: ['sprites/*.png'],
                    destImg: 'public/images/sprite.png',
                    destCSS: 'less/sprite.less',
                    cssFormat: 'less',
                    imgPath: '../images/sprite.png'
                }
            },
            less: {
                dist: {
                    options: {
                        paths: ['less']
                    },
                    files: {
                        'public/stylesheets/site.css': 'less/site.less'
                    }
                }
            }
        });
    
        grunt.loadNpmTasks('grunt-spritesmith');
        grunt.loadNpmTasks('grunt-contrib-less');
        grunt.registerTask('default', ['sprite', 'less']);
    };

    You should also note that I've changed the default task to first generate the spritesheet and then compile the LESS stylesheet. You should now be able to run grunt again to have your stylesheet generated.

    $ grunt
    Running "sprite:dist" (sprite) task
    
    Running "less:dist" (less) task
    File public/stylesheets/site.css created.
    
    Done, without errors.

    You can now use individual images on your spritesheet by using the classes we defined. Here is an example HTML file using the windmill image.

    <!DOCTYPE html>
    <html>
    <head>
        <link rel="stylesheet" type="text/css" href="stylesheets/site.css">
    </head>
    <body>
        <div class="windmill-image"></div>
    </body>
    </html>

    Finally, here is what an individual image being used looks like.

    Now that you've automated your spritesheet generation, you will be able to easily add more images to the sprites folder and run grunt again to generate a new spritesheet.

    C# Delegate Multicasting

    January 29, 2013

    Microsoft's .NET framework uses the delegation design pattern extensively. Every time you use an event handler you are using delegation. There are several different ways to implement delegates in .NET, but multicasting is clearly the most flexible way and the one used by Microsoft's classes. In Visual Studio, this happens somewhat automagically through the user interface.

    I frequently use delegates with the Unity game engine and wanted to create the shortest possible example using the latest syntactic sugar. The following is what I came up with.

    An example of a class that delegates in MyDelegator.cs:

    namespace MyNamespace {
        public delegate void MyDelegate();
    
        public class MyDelegator {
            public MyDelegate MyHandler { get; set; }
    
            public void DelegateStuff() {
                if (MyHandler != null) {
                    MyHandler();
                }
            }
        }
    }

    And a class that gets delegated to in MyDelegatee.cs:

    using System;
    using MyNamespace;
    
    namespace MyProgram {
        public class MyDelegatee {
            static void Main() {
                MyDelegator myDelegator = new MyDelegator();
    
                myDelegator.MyHandler += SomeMethod;
                myDelegator.MyHandler += SomeOtherMethod;
                myDelegator.DelegateStuff();
            }
    
            public static void SomeMethod() {
                Console.WriteLine("SomeMethod");
            }
    
            public static void SomeOtherMethod() {
                Console.WriteLine("SomeOtherMethod");
            }
        }
    }