Custom launch arguments and environment variables

While developing iOS apps, it can sometimes be useful to temporarily redefine the default behavior of your app for convenience or debugging purposes. For example, maybe you’re working on a first-run feature—a tutorial, for instance—that users should only see the first time they open your app. In production, you might want this feature to appear based on a flag stored in NSUserDefaults:

BOOL tutorialShown = [[NSUserDefaults standardUserDefaults] boolForKey:@"tutorialShown"];
if (!tutorialShown) {
    [self showTheTutorial];
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"tutorialShown"];
}

While building this feature, however, you want it to appear every time you build and run. What are your options in this situation? Well, you could comment out chunks of code to force the feature to show up while you’re working on it:

// BOOL tutorialShown = [[NSUserDefaults standardUserDefaults] boolForKey:@"tutorialShown"];
// if (!tutorialShown) {
    [self showTheTutorial];
//  [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"tutorialShown"];
// }

The simplicity of this approach is tempting, but the disadvantages are fairly obvious. For one, you have to remember to uncomment the code before committing it to your repository. This can be especially annoying (and even dangerous) if you’re working with other people who might have difficulties with—or worse, accidentally ship—your temporarily commented-out version.

Another approach might be to use a preprocessor conditional, perhaps based on a custom build setting in your prefix header file, your project, or a .xcconfig file:

#if ALWAYS_SHOW_TUTORIAL
[self showTheTutorial];
#else
BOOL tutorialShown = [[NSUserDefaults standardUserDefaults] boolForKey:@"tutorialShown"];
if (!tutorialShown) {
    [self showTheTutorial];
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"tutorialShown"];
}
#endif

This is better, but it still shares some major disadvantages with commenting out the code. As above, you’re still making changes you’ll have to revert, and you and your coworkers still run the risk of using the wrong build settings when archiving the app for production if you’re not careful.

The best way I’ve found to deal with this scenario relies on a combination of the preprocessor and custom launch arguments defined in an Xcode scheme. You may be familiar with launch arguments and environment variables already, but if not, you should check out this great guide on NSHipster. In addition to controlling the behavior of the frameworks you’re using, launch arguments can be great for overriding boolean flags in your own code during development:

BOOL tutorialShown = [[NSUserDefaults standardUserDefaults] boolForKey:@"tutorialShown"];
#ifdef DEBUG
if ([[[NSProcessInfo processInfo] arguments] containsObject:@"-always_show_tutorial"]) {
    tutorialShown = NO;
}
#endif
if (!tutorialShown) {
    [self showTheTutorial];
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"tutorialShown"];
}

If you need to override specific non-boolean values, environment variables are a great alternative to launch arguments. For example, if you’re working on a login screen for your app, it might be useful to pre-populate your username and password text fields with default values, while avoiding committing sensitive information to your repository:

#ifdef DEBUG
NSDictionary *environment = [[NSProcessInfo processInfo] environment];
[[self usernameField] setText:environment[@"USERNAME"]];
[[self passwordField] setText:environment[@"PASSWORD"]];
#endif

If you typically use a shared scheme for building and running your app (which is committed to version control), make sure to duplicate it locally before making these additions. Oh, and make sure you’re using the latest and greatest gitignore file for Objective-C development.

Have a different way of doing things? Let me know on Twitter. Thanks for reading!

Remove the arm64 architecture from CocoaPods targets

It’s been a few months since Apple released the first iDevices to feature 64-bit support. While many developers have embraced the impending 64-bit future, not all third party libraries support this architecture yet, including those installable via CocoaPods.

Despite the lack of universal 64-bit support among 3rd-party pods, CocoaPods still includes the arm64 architecture (via ARCHS_STANDARD_INCLUDING_64_BIT) in its generated targets’ build settings. This can cause problems if your app’s dependencies don’t support arm64, or you only want to build for armv7 and armv7s for other reasons.

Fortunately, there’s a quick and easy automated fix. Just add the following to the bottom of your Podfile to revert the ARCHS build setting to ARCHS_STANDARD:

# Remove 64-bit build architecture from Pods targets
post_install do |installer|
  installer.project.targets.each do |target|
    target.build_configurations.each do |configuration|
      target.build_settings(configuration.name)['ARCHS'] = '$(ARCHS_STANDARD_32_BIT)'
    end
  end
end

To test, target the “iPhone Retina (4-inch 64-bit)” simulator and build.

Update: The latest Xcode 5.1 beta redefined ARCHS_STANDARD to include arm64. I’ve updated the code above with a fix.

On Interface Builder

The other today I came across a blog post and some interesting comments on Twitter about Interface Builder and its role in iOS development.

Every iOS developer seems to have an opinion about Interface Builder (generally referred to as “IB”). Many label the much-maligned tool as a crutch for beginners who don’t understand how to code a UI from scratch. Others claim to use it almost exclusively for UI development, even to the point of encouraging non-coders to dig their teeth into the world of .xib files directly. I have a feeling most opinions are somewhere in the middle–torn between the “no IB whatsoever” and “use IB for everything” viewpoints.

While it’s true you can’t quite build an app entirely in IB, it’s still a powerful tool that lets you minimize the amount of boilerplate code you have to write to build an interactive UI. In recent years, its capabilities have grown with the addition of storyboards, gesture recognizers and autolayout support. Still, there are a few shortcomings that are difficult to overlook, including lack of support for resizable images, pattern colors, animations, and constants shared with code, just to name a few.

It seems clear to me that our tools will never be perfect, and both code and GUI-based UI development have a long way to go. Whenever I consider this situation, a couple maxims spring to mind:

Use the best tool for the job.

Here are a couple of reasons why I think IB is not only a great choice for UI development, but should be understood and used by all app developers:

Consistency is better than perfection.

The best way I’ve found to take advantage of the most desirable properties of IB and code-based development is to come up with, and adhere to, some basic conventions. These conventions can be as simple or as complicated as needed, but here are a few examples:

Every developer should at least have a few conventions in mind, but it might help to write them down somewhere. If you use GitHub, a wiki would be a great place to list these things out, along with any other general comments/instructions that don’t belong in code-level comments or a README file.

My opinions may evolve over time, but for now I plan to continue exploring Interface Builder’s capabilities, and to stay as rational as possible when it comes to making decisions about which tools to use to get my job done.

Information overload

It occurred to me today that I consume a lot of information. Too much information. All those productivity blog posts that talk about anxiety from the little red notification badges? That’s where I am right now (as my ability to reference such blog posts should tell you). I’ve decided to take control of my information consumption habits, with the following goals in mind:

  1. Maximizing the signal to noise ratio. It’s 2012; I should be reading/hearing only what’s relevant to me.
  2. Spending less time consuming and more time thinking. I’m finally accepting that there’s just too much information out there for me to process, even after it’s completely filtered, and spending more time consuming means less time thinking, doing and creating.

Here are the top three actions I’m taking to work toward these goals.

  1. Unsubscribe from all email newsletters and notifications. I’m adopting a zero-tolerance policy when it comes to email newsletters and notifications. In lieu of relying on email for relatively unimportant notifications from services like Facebook and Twitter, I’ve decided to put my trust in Apple’s push notification system.
  2. Trust the experts. I spend a lot of time working through feeds in Google Reader every day. I’ve become pretty efficient when it comes to choosing the articles I think are most interesting or relevant to me. But for some people, separating out the best articles from the rest is a full-time job. When it comes to many sources of information, I’m willing to trust those people to do the filtering for me.
  3. Return to long-form reading. I spend a lot of time reading, but it’s usually blog posts from RSS feeds, and I usually spend no more than five or ten minutes reading at any given time. For many of the topics I’d love to learn more about, that’s simply not going to be enough. I have stacks of novels and non-fiction books at home that I’m itching to spend some time with.

The epiphany I had today is that just reading (or listening, or otherwise “getting”) information is not, in and of itself, productive or fulfilling. I’m hoping that realization will serve me well going forward.

A great preprocessor use case

Just came across an interesting use of preprocessor #defines in one of Apple’s Grand Central Dispatch headers:

#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/dispatch.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif

If you look at dispatch/dispatch.h, you’ll see the following:

#ifndef __DISPATCH_INDIRECT__
#define __DISPATCH_INDIRECT__
#endif

Seems like a good way to manage complex multi-file compile-time dependencies. I’m sure there are lots of other cool preprocessor use cases hiding in these headers, too.

Using multiple Dropbox accounts in Mac OS X

This post has been written before, but it’s such a useful hack that I figured I’d share it here for those who haven’t seen it. It’s particularly useful for people who want to use separate “home” and “work” Dropbox accounts.

Running two instances of Dropbox.app

The trick is to get Mac OS X to run multiple instances of Dropbox.app at the same time. As far as I’m aware, there’s no way to do this through the Finder (for any application). Fortunately, it’s easy to do in two Terminal commands:

mkdir -p "$HOME/.dropbox-alt"
HOME="$HOME/.dropbox-alt" open -n -a Dropbox.app

(You can replace .dropbox-alt with whatever you want).

The first line simply creates a new hidden folder in your home folder, if it doesn’t already exist. Although it looks like the second line should be two commands, it’s really just one. Invoking open with the -n flag causes a new instance of the application to launch (and if you use the -a flag, you don’t need to specify the full path to the Dropbox app). Setting the HOME environment variable to its new value fools the new Dropbox instance into thinking your home folder is at $HOME/.dropbox-alt. Since Dropbox normally stores its settings in your home directory, you can have a new set of preferences in this folder that doesn’t conflict with your primary account.

After you run those lines in Terminal for the first time, the new Dropbox instance will prompt you to set up your account. Once you go through the initial setup, running those commands will simply launch the second Dropbox instance and begin syncing your files.

Launch a second Dropbox instance automatically

While it’s not difficult to run these commands, it can get tedious after a few logins. Wouldn’t it be nice if you could start your alternative Dropbox from Finder, or start it automatically when you log in? With Automator, you can do just that.

Here are the steps:

  1. Launch Automator (/Applications/Automator.app).
  2. Create a new “Application” document.
  3. In the Actions library, search for “Run Shell Script”.
  4. Double click or drag the “Run Shell Script” action into the workflow (on the right).
  5. Select /bin/sh from the “Shell” menu, and paste the two Terminal lines above in the text area.
  6. Save the result to your Applications folder (call it “Dropbox Alt.app” or something similar).

Now you can launch your secondary Dropbox instance by running the application you just created! To add it as a login item:

  1. Go to System Preferences and search for “Login Items” in the search bar.
  2. Click the plus and add your “Dropbox Alt” application.

Hope you find this as useful as I do!

Moving to Jekyll

It’s been a while since I’ve posted anything around here, and I’d like to change that. Part of the reason for the lack of updates (or so I tell myself) is because nanoc, while extremely flexible and customizable, proved increasingly difficult to use over time. A major version update broke my build process, and I ended up spending more time engineering my blog than writing–I even had to write my own gem to deploy my site to GitHub. I’m hoping that using a system that integrates better with GitHub will let me get back to what I originally set out to do with this site.

Implementing Oplop in Python

I’ve been using Oplop for a while now. It’s a great alternative to database-style password management programs like 1Password, providing the same level of security without compromising portability. While 1Password lets you take your passwords with you via an encrypted file and mobile, web and desktop apps, Oplop makes it so you don’t have to take anything with you at all!

One thing I don’t like about Oplop, however, is having to go to oplop.appspot.com every single time I need to retrieve my passwords. So I decided to implement the algorithm as a Python script with a simple command line interface.

#!/usr/bin/env python

"""Generate a password using the Oplop password hashing algorithm.
For more information: http://code.google.com/p/oplop/wiki/HowItWorks"""

from sys import argv, stdout
from hashlib import md5
from base64 import urlsafe_b64encode as b64
import re

PASS_LEN = 8
DIGIT_RE = re.compile('\d+')

def oplop(nickname, master_password, pass_len=PASS_LEN):
    hashed = b64(md5(master_password + nickname).digest())
    digits = DIGIT_RE.findall(hashed[:pass_len])
    if not digits:
        digits = DIGIT_RE.findall(hashed)
        hashed = (digits and digits[0] or '1') + hashed
    return hashed[:pass_len]

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('nickname', help='Account nickname')
    parser.add_argument('master_password', help='Master password')
    args = parser.parse_args()
    stdout.write(oplop(args.nickname, args.master_password))

From here, I just need to come up with a way to get passwords generated by the script into web forms and applications automatically. For now, Alfred (+ Powerpack) and pbcopy are doing nicely.

Here’s the Gist.

Easily create a UIImage from a UIView

One of my projects at Aviary necessitated generating a static UIImage from a UIView. Fortunately, Quartz makes it really simple to do this. Here’s a quick category on UIView showing how it can be done.

To explain: -createImageFromRect: method generates an image by rendering the portion of the view bounded by “frame” in an image context. Note that CALayer’s -renderInContext: method renders the entire layer tree, creating a flat image from the view hierarchy.

/* implementation UIView (UIImageCreation) */

- (UIImage *)createImageFromRect:(CGRect)frame
{
    UIGraphicsBeginImageContext(frame.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGPoint origin = [self bounds].origin;
    CGPoint offset = frame.origin;

    CGContextTranslateCTM(context, origin.x - offset.x, origin.y - offset.y);

    [[self layer] renderInContext:context];

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

- (UIImage *)createImage
{
    return [self createImageFromRect:[self bounds]];
}

/* end */

Check out the Gist here.

Aviary HQ

A lot has happened in the past month or two, but the biggest news from me is that I started working at Aviary, Inc. in mid-July. I’ve been spending a good deal of time at the office, and I’m loving every minute of it. Our building is in the heart of Manhattan, right next to Penn Station and Madison Square Garden. We have an amazing roof and a really sketchy elevator. Hmm, reminds me of somewhere in Bushwick.

Reflecting on Year One in NYC

It’s been an eventful year since I graduated last summer, made the transition from Cambridge to Bushwick. There’s much more to this story, but I’m hoping this quick retrospective will kickstart this blog back into action.

Work

A year ago was an exciting time for us: some friends and I had made a successful iPhone app together, been profiled by the Wall Street Journal, and received enough money from AT&T to work on mobile apps for schools AND live off of for a year. Times were good.

We worked hard to get our work off the ground, finding our way with AT&T, some of their partner companies, and of course, universities, and ended up deploying the Columbia Business School mobile app last month after a year of hard work. While we didn’t quite take our business to the level we wanted, we ended up with a product we can be proud of.

As our team heads off in different directions, things are getting exciting once again. I’ll have more to tell in a little over a week.

Life

I’m convinced I’m a different person than I was when I arrived in New York City. It took a long time for me to get over how dirty, crowded and expensive it can be, but I’m learning to love it here–there really is no place like it. I’ve particularly enjoyed the live music scene.

Bushwick has been great to me, and I’ll miss it when I leave for Manhattan. I’m consistently amazed at how lucky we got with our apartment–even though our building has been an unexpected (or unwanted) adventure at times, we’re around the corner from the L train, we now have a 24-hour grocery store across the street, and there are restaurants and shops popping up everywhere. We couldn’t have asked for a better introduction to the city.

Happy New Year, NYC!

I have lots of goals for the next year: getting a bike and commuting above-ground, getting more involved in the NYC startup scene, and meeting more people, to name a few. It’s definitely going to be a busy year. Oh, and more concerts.

And, once again, I hope to make this blog worth reading!

Thompson LES

I went to a birthday party at a top-floor room at the Thompson LES (LES = “Lower East Side”) on Sunday. As far as I can tell, it’s the tallest building in the area, which made for an absolutely spectacular night-time view from the private deck. The room spans the length of the building and faces west, making for a perfect view of both the financial district, the Brooklyn Bridge, and midtown. I shudder to think what it would cost to actually stay here, and I’m glad the only cost to me was a bottle of rum.

New Ashiya

This is the first of what will hopefully be an ongoing series about places and businesses I’ve visited.

New Ashiya is a sushi restaurant on 1st Ave in the East Village. It looks pretty innocuous on the outside, but walk inside and you’ll immediately see that this isn’t your average Japanese restaurant. In addition to their regular menu, they have an all you can eat and drink option for $33 per person. For 2 hours, you can order as much sushi, sake and beer as you can handle (without going overboard–the menu warns of additional charges for wasted food). We opted to try every special roll on the menu (about 10 different kinds), plus some tuna and salmon sashimi. The highlight was definitely the black pepper tuna roll, something I’ve never seen or tasted anywhere else. Oh, and we did lots of sake bombs.

My Password Management Setup

Since my last post on identity theft/worst case scenarios regarding user accounts on the web was a bit technical/unclear, I figured I’d follow up with a better answer to the question: “so what should I do about it?” Since weak passwords and site-specific attacks are the biggest threat, I think the best way for me to answer that question is to walk through my current account management scheme.

My system runs on one simple rule: don’t use the same password twice. When I register new accounts online, I use a different password every time. That way, if one site I use gets compromised, my other accounts won’t be affected. Obviously, this would be impractical if I had to remember every single password I registered with, or even if I had to keep them all written down. So here are the supporting requirements of my system:

  1. Keep memorization to a minimum. I don’t want to waste brain power memorizing hundreds of passwords.
  2. I should be able to access my passwords quickly–only slightly slower than the same amount of time it would take to recall them from memory and type them out.
  3. I should be able to access my passwords wherever I am.

I’m basically looking for the convenience of using a single password everywhere, but with much better security. Fortunately, this is easily accomplished using a few tools and some initial setup time.

These two tools allow me to satisfy my three requirements above. Both of them allow me to avoid memorizing any passwords except the master. When I’m on my own computer, 1Password’s browser plugins allow me to fill out login forms with a single keystroke. When I’m on someone else’s computer, I can look up my password on my iPhone or use Oplop to retrieve it.

This isn’t necessarily the simplest system to set up–after all, it requires you to change all your current account passwords and your behavior. But I can guarantee that if you do both, you’ll be protecting yourself better than most other internet users.

On Internet Disaster Preparedness

Most people don’t worry about keeping themselves safe online. However, like backing up your files, it’s something that many only realize they need when it’s too late.

Yesterday, a friend of mine met with an unpleasant surprise when she logged into her iTunes account: someone had gained access to her account, and had made a $100 purchase using her credit card. While this charge can and will be quickly revoked, she faces a more serious problem. Like most people, she uses the same password for many other accounts online, meaning that her other accounts could also be compromised.

First, let’s look at a couple of the possible ways she could have gotten hacked:

  1. She is a victim of session hijacking.

    Many sites use HTTPS to protect their users’ data from being intercepted by a third party. However, many sites still use the faster, but less secure HTTP protocol. Using tools like the widely publicized Firesheep, attackers can take control of a user’s login session. While most sites wouldn’t allow them to change the account password without access to a registered email account, they could still access sensitive information and generally wreak havoc. As more sites adopt the use of HTTPS by default, this will become less of a problem, but a universal solution has not yet been implemented.

    In order to protect yourself from this kind of attack, you should do the following:

    • Think twice before accessing an HTTP-only service on a public wi-fi network. You can tell if you’re using HTTP or HTTPS by looking at the beginning of the URL in your browser’s address bar (http://... vs. https://...).
    • Enable HTTPS as the default protocol on sites that offer the option. For example, in Facebook, go to your account settings and enable “Secure Browsing (https)” under “Account Security”.
    • Use a secure proxy service like the cloak or similar, or (for more advanced users), tunnel your traffic to a trusted server via SSH.

    As with all of these attacks, if you become a victim, you should change your password immediately.

  2. The attacker knows her password, either by guessing or by exploiting a vulnerability in another site.

    This is by far the most dangerous situation. It’s only likely to happen if you use the same password for many sites, but this is, unfortunately, the case for many people. Let me put this as simply as I can: you should not rely on sites to keep your password safe. Recently, users registered on the Gawker network learned this the hard way.

    The best way to protect yourself against site vulnerabilities is to use a different password for every account you register. It’s not as hard as you might expect, and there are a lot of different utilities out there that make it very easy to do. I use a combination of oplop and 1Password. Both of these utilities rely on the idea of a single “master” password that you memorize, but instead of exposing this master password to the outside world by using it to register accounts, you use it to generate and protect your set of unique, account-specific passwords, none of which are important to memorize. It’s an extremely secure system, and very convenient once you get used to it.

  3. The attacker found and exploited a security vulnerability in iTunes that allowed him/her to gain access to the account.

    This is similar to the situation above, and the only way to protect yourself is to change your account password. If the service you’re using is unreliable, you should strongly consider removing all personal information from your account and using something else.

In all situations, the best thing you can do is change your password(s), and be eternally skeptical any time a site guarantees the safety of your information. With our increased reliability on internet services to accomplish vital tasks like online banking, it is always a good idea to be overly cautious.

Also, I could write an entirely different post about this, but continuing in the spirit of being prepared for disasters: go back up your important files NOW. With free services like Dropbox readily available, you have no more excuses not to.

Music is Life is Music

I got the title from some random ad in my subway station, but it’s kind of true. Music has been an integral part of my life from piano lessons—for about 8 years of my life—to singing in high school and college, to playing guitar and listening to music on my iPhone and computer just about 24/7. Programming, traveling, relaxing: music plays a part in nearly everything I do.

In all the ways I’ve interacted with music, one mode has affected me more than all the others: being at concerts. Back in middle school, I saw Tom Petty at Red Rocks, and I’ve been absolutely addicted ever since. Unfortunately, rather than satisfying that addiction, I’ve spent most of my time having withdrawals and flashbacks to the last great show. It’s not that the Denver area hasn’t historically attracted some big names—the Beatles even made a stop at Red Rocks on their 1964 world tour—and I certainly had a decent selection while I was in Boston. It’s just been all too easy for life and school to get in the way.

One of the great things about living in New York is that almost every artist I currently listen to has performed in the city during the time I’ve lived here (since June 2010). Add decent public transportation to an abundance of great concerts, and you get a recipe for awesome. Or spending a lot of money on concert tickets. Or both.

It’s true, concerts are loud (sometimes eardrum-splittingly so), crowded, messy and expensive. But there’s really nothing quite like hearing your favorite songs being played by their creators for you, and for me, there’s no expense too great to have that. This is one addiction I don’t plan on giving up for the rest of my life.

In case anyone is curious/cares, here is basically every major concert I’ve been to: