Fickle Bits

You're doing it wrong.

75 Essential Tools for iOS Developers

If you were to go to a master woodworker’s shop, you’d invariably find a plethora of tools that he or she uses to accomplish various tasks.

In software it is the same. You can measure a software developer by how they use their tools. Experienced software developers master their tools. It is important to learn your current tools deeply, and be aware of alternatives to fill in gaps where your current ones fall short.

With that in mind, I present to you a gigantic list of tools. Some of these I use daily, others I see potential in. If you have more tools you’d like to see here, just make sure to add a comment.

Speaking at Cocoa Conf PDX

I have the pleasure of speaking at Cocoa Conf PDX on August 15-16th. Cocoa Conf is always a great event, and I especially love traveling to my home state of Oregon. This time around I’ll be giving two talks:

  • The iOS Developer’s Toolbelt
  • Jenkins - Your personal butler for iOS automation

I hope to see you there!

In Search of a Fast External Hard Drive

Ever since I upgraded to a retina MacBook Pro, I knew I’d have to come up with a new strategy for storing data. Even after upgrading to the 512GB SSD, I’m still running out of space. With hundreds of gigabytes for pictures, music, videos, and games a 512GB SSD is perfectly reasonable. But now that NSScreencast is nearing a year old I have more data than I can store on a single drive. Another nuissance was transferring these videos over to my iMac for editing.
A typical 20 minute screencast of mine will eat up nearly 8 gigabytes before encoding, and transfering a file like this over Wi-Fi is painfully slow.

On my previous MacBook Pro I opted to remove the superdrive and install a 2nd 7200 RPM drive for larger storage. This worked well, but the retina MacBook Pro has no such capability, so I went on the lookout for an external drive to store NSScreencast videos.

Serving Assets From S3 on Heroku

Recently I changed NSScreencast to use a CDN to serve up assets from a different, faster server.

Why use a CDN?

Using a CDN has numerous benefits. First, and foremost, this alleviates a bunch of secondary requests that would normally hit your webserver. Loading the home page of NSScreencast loads more than a dozen images, stylesheets, and javascript files. When deploying to Heroku this can be especially problematic as each asset request will occupy one of your dynos for a short time. In the spirit of maximizing your free dyno on Heroku, not sending these requests to your app is definitely a big win.

In addition, most browsers have a setting that limits the number of connections (usually 2) that it will open in parallel to a given domain. By using a CDN, you can increase the number of parallel requests because these assets are not served up by your application’s domain.

It’s also a common practice to use dns to “alter” the domain so that you can maximize this parallelization.

Using the asset sync gem

Following the instructions on Heroku’s Devcenter article I decided to use the asset_sync gem. This gem will upload your compiled assets to your preferred CDN (any file storage server that fog supports). In my case, I wanted to use S3.

The first step is adding this gem to your Gemfile:

1
2
3
4
group :assets do
  # other asset gems
  gem 'asset_sync'
end

It’s important to put this in your asset group, as your running app doesn’t need to load this into memory.

Then you need to configure the gem. I found Heroku’s instructions to be lacking here, as I had to dig into the asset_sync github page to make this work.

Add a file called config/initializers/asset_sync.rb to your app:

1
2
3
4
5
6
7
8
9
10
11
12
13
# Since this gem is only loaded with the assets group, we have to check to 
# see if it's defined before configuring it.
if defined?(AssetSync)
  AssetSync.configure do |config|
    config.fog_provider = 'AWS'
    config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
    config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
    config.fog_directory = ENV['FOG_DIRECTORY']

    # Fail silently.  Useful for environments such as Heroku
    config.fail_silently = true
  end
end

That last config line is important. When you deploy to Heroku, your app’s assets will get precompiled. But because Heroku doesn’t initialize your app on precompile, none of your settings will be available. Instead we’ll have to run the precompile again, manually, to get AssetSync to kick in.

Setting up the configuration with Heroku San

Since I like to have multiple environments, I use heroku_san to manage them, including the environment variables.

Inside of config/heroku.yml, set up the following for each environment:

1
2
3
4
FOG_PROVIDER: "AWS"
FOG_DIRECTORY: "nsscreencast-assets"
AWS_ACCESS_KEY_ID: "<your access key>"
AWS_SECRET_ACCESS_KEY: "..."

Configuring Your Rails app to use S3 as an Asset Host

In your config/production.rb (and staging.rb if you have one), make sure to add the following line to allow Rails to generate the appropriate links for your assets:

1
2
3
4
  config.action_controller.asset_host = Proc.new do |source, request|
    scheme = request.ssl? ? "https" : "http"
    "#{scheme}://#{ENV['FOG_DIRECTORY']}.s3.amazonaws.com"
  end

This will allow your app to serve up the URLs using SSL if the request is coming via SSL. Doing this can avoid warnings in the browser that your app contains secure and unsecure content.

Testing it all out

If all of this is configured correctly, you can test it out by doing a push…

1
git push heroku master

You’ll see the asset precompile going on in the logs, and likely an error related to AssetSync. This is fine (and in fact, this tripped me up at first). Once the deploy has completed, you’ll have to run this command to upload your assets:

1
heroku run rake assets:precompile --app <yourapp>

Doing this, you should see something like the following output:

1
2
3
4
5
6
Precompiling assets...
Uploading: application.css
Uploading: application.css.gz
Uploading: image1.png
Uploading: image2.png
...

Set up Heroku San to do this on every deploy

I’d likely forget to run this command every once in a while, so I set up Heroku San to run this command after every deploy.

To do this, add a new rake task in your app (lib/tasks/deploy.rake):

1
2
3
4
5
6
task :after_deploy do
  HerokuSan.project.each_app do |stage|
    puts "---> Precompiling asssets & uploading to the CDN"
    system("heroku run rake assets:precompile --app #{stage.app}")
  end
end

Now when you run your deploy via rake production deploy this will happen automatically.

So what’s the net result?

Doing this alleviated nearly 30 secondary requests to my application for each page load. That alone is pretty huge. Also, S3 is much faster at serving these assets than nginx is (at least via a Heroku app on 1 dyno).

I tested this before and after by clearing the cache and doing a fresh page load. Using the Chrome Inspector, I looked at the time to load the page and all assets. Here are my findings:

Before (serving assets with no CDN) 3.27 seconds
After (using S3 as a CDN) 1.07 seconds

That’s a huge gain for a minor change in your application & deployment process.

Hello, NSScreencast

NSScreencast is now live. The first 2 videos have been posted:

Now that the site has launched, I can share more details with you about it.

A new video each week

Each week, a new video will be posted covering a single, focused topic related to iOS development.

Don’t waste the listener’s time

Each video will be short and to the point. It boils down to this: a 20 minute video is an easy thing to watch. A 60-minute video is a serious time commitment.

Some Free, Some Paid

Eventually, NSScreencast will be a subscription service. I’ll announce details once they are nailed down, but for now, enjoy the videos! If you’d like to be notified when an episode is released, you can subscribe to the RSS feed, or follow @nsscreencast on twitter. (Subscribing in iTunes is coming soon)

If you have any video topic suggestions, feel free to share them at the User Voice Forum. Seriously, I’d love to hear your feedback!

NSScreencasts, Coming Soon

Bite-Sized Learning

Video training is becoming a very common way to learn these days. With Tekpub, Peepcode, Pluralsight, Code School, and many others, there are usually great productions to teach you any development topic that you’d want to learn about.

All of these services are great, however I’m becoming a fan of the smaller, more focused screencasts. Railscasts, for instance, has been instrumental to my Rails learning development. Destroy all Software teaches me new things every week.

Smaller videos like this are easier to digest, and are more focused on a single topic. Like the boiled frog you eventually realize how far you’ve come on a topic, simply by watching regular videos.

iOS Development is an ever-changing landscape, with so many topic areas to cover, that a single training class or screencast series just can’t teach you all of it. Instead of trying to cover everything in depth (increasing the length of videos). I find it valuable to have smaller, focused tutorials that teach you one thing, and do it quickly and effectively.

Introducing NSScreencast

NSScreencast will be launching soon and will feature regular bite-sized videos focused on a single topic related to Objective-C and building iOS applications.

NSScreencast will include free videos. Down the road, a nominal paid subsribtion will unlock access to more content.

I still have lots to do before I release the first video, but if you like the idea, please sign up on the site to be notified when it launches. Thanks!

Careful With Block-Based Notification Handlers

In general, I prefer using block-based APIs over those that accept selectors.

The block based APIs are generally easier to read & follow, and don’t clutter up your class with methods that are out of context with the code that might potentially invoke them.

An Example

One good example is view animations. Here we’re fading out a view and removing it from the hierarchy once the view has been completely faded out. It’s concise, easy to read, and you don’t need to go anywhere else in the class to get a complete picture of how this works.

Also, since you can have multiple animations going on, having a block-based completion handler means you don’t have to distinguish between what the animations were in some generic completion method.

1
2
3
4
5
[UIView animateWithDuration:0.5 animations:^{
  someView.alpha = 0;
} completion:^ (BOOL finished) {
  [someView removeFromSuperView];
}];

Contrast this with the non-block version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (void)fadeOutView {
  [UIView beginAnimations];
  [UIView setAnimationDuration:0.5];
  [UIView setAnimationDelegate:self];
  [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];

  someView.alpha = 0;

  [UIView commitAnimations];
}

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
  [someView removeFromSuperView];
}

Block-Based Notification Handlers

NSNotificationCenter also got some block love when iOS SDK 4.0 came around. The old form looked like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (void)setupNotifications {
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(onWhizBang:)
                                               name:MyWhizBangnotification
                                             object:nil];
}

- (void)onWhizBang:(NSNotification *)notification {
  // reload the table to show the new whiz bangs
  [self.tableView reloadData];
}

- (void)dealloc {
  [[NSNotificationCenter defaultCenter] removeObserver:self];
  [super dealloc];
}

This isn’t a lot of code (and it is easy to remember, unlike the previous UIView animation block code), however the action and the notification handler are separated from each other.

The block-based API looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)setupNotifications {
  [[NSNotificationCenter defaultCenter]
      addObserverForNotificationName:MyWhizBangNotification
                              object:nil
                               queue:[NSOperationQueue mainQueue]
                               block:^(NSNotification *notification) {
                                 //reload the table to show the new whiz bangs
                                 [self.tableView reloadData];
                               }];
}

- (void)dealloc {
  [[NSNotificationCenter defaultCenter] removeObserver:self];
  [super dealloc];
}

Aside from some funky indentation, this is preferable in some cases, especially when the action to be completed is as simple as reloading the table.

But there’s a bug. Can you spot it?

Blocks Are Closures

There’s a subtle bug here that you might not notice at first. I didn’t realize this until it was littered all over my code base.

Blocks are closures, and they will capture any values declared outside the scope of the block (and retained) so that they can be used when the block executes. This includes variables declared in the enclosing method or any ivars that you reference from inside the block.

Here, we used self.tableView. self gets retained by the block, which is also retained by self. We have a retain-cycle which is generally a bad thing. It’s especially bad here, because we don’t clear out the block until dealloc, but dealloc won’t ever be called because the block is retaining the instance!

Weak Pointers Save the Day

If you’ve read up on blocks, you’ve probably seen the __block keyword. This specifier tells blocks not to retain the pointer. So all we need is a new pointer, like so:

1
2
3
__block MyViewController *weakSelf = self;

// use weakSelf in the blocks, instead of self

This sort of code drives me nuts. It won’t be apparent to the next developer why it’s there, and it’s pretty ugly.

Retain Cycles are Elsewhere, Too

You might also run into this if you have a parent-child view controller relationship, or perhaps a an parent->object->delegate chain, where the parent is the delegate. This is why you typically mark your delegate property signatures with assign instead of retain semantics.

Not all retain-cycles are terrible though. If you have a way of breaking the cycle, then you just need to weigh how long these objects will remain active for to decide if you need to fix it.

Hopefully this will save you a few headaches down the line.

Formatting JSON From Terminal

I work with JSON APIs a lot. On a current API I work on, there is an OAuth-esque request signing process that is required to make sure that others cannot forge requests simply by changing parameters arround.

A typical request might look like this:

1
2
3
4
5
6
7
8
9
HTTP 1.1
GET /foo/bars.json

Headers:
    Accept-Encoding = gzip;
    Accept = application/json
    Authorization = "cHOLIOb7bAeqFEmsz3io%2Bxg4sQA%3D";
    Account-Id = 201;
    User-Agent = "...";

The Authorization header is generated by concatenating the HTTP Method, URL, any parameters, and then signed with a key.

Because of this security, it is very difficult to create adhoc requests just to try them out. So instead, we have our iPhone app NSLog the proper curl command for us. Now it’s as simple as copy & paste from the Xcode Console, which gives me a less-than-readable output of the JSON.

Usually for this I just pipe the command into pbcopy to get it on my clipboard, then I visit JSON Lint to make it easy to read.

Doin’ it all from Terminal

I looked at ways of doing this all from the Terminal, and came across this python command:

1
python -mjson.tool

It takes input from stdin and outputs it formatted nicely. Sweet! Now all that’s needed is to make this a bit more easy to remember, so I made a script to do this for me called format_json and put it in my path.

Now, any time I want to see the JSON output of an API, I can simply type:

1
2
$ curl some.server.com/api/devices.json?key=124512312 -H Authorization:"124151231231123123" |
    format_json

And here is the output:

1
2
3
4
5
6
7
8
9
10
11
12
{
  "devices": [
      {
          "device_id": "40f4fc8a5818608dbb9a6c981179222b6f",
          "device_type": "iPhone",
          "id": 24,
          "name": "Ben's iPhone",
          "push_enabled": true,
          "push_token": "a3a36......480c25fdf"
      }
  ]
}

Very handy, indeed.

Houston Tech Fest 2011 Recap

Houston Tech Fest 2011 came and went, and yet again was a great success. I believe it was the biggest one ever, with over 1,300 registrants.

I gave three talks:

You can find the slides & code used in the presentations here on github.

If you attended any of these sessions, I’d really appreciate if you rate them using the links above.

See you next year, Houston Tech Fest!

Appsites Is Now AppKickstand

A few weeks ago I launched Appsites, a free way to quickly host an attractive splash page for iPhone applications.

Instead of competing with another site with the same name for traffic when we could be sharing it, I decided a new name was in order.

I now present to you: AppKickstand.

AppKickstand

For an example of what it looks like with real apps, check out Giggle Touch or Tally Things.

If you have an iPhone app, what are you waiting for? It’s FREE!