Upcoming Classes

RSS Feeds

Categories

Archive

Site search

Going to Voices That Matter Seattle?

Voices that Matter is going to let me do the keynote on the first morning of their iOS conference this spring. The conference is April 9 and 10 in Seattle. You should come — it is a well-run and informative gathering. (Early-bird pricing ends on Feb 25, so sign up now.)

If you are coming, you might want to consider signing up for the one-day introduction to iOS programming that I’m doing the day before.

New Kindle version of “iPhone Programming” book

Making a .epub or .mobi version of a book is not as easy as it looks. Until recently, if you bought the Kindle version of our iPhone book you were buying something that was generated from our PDF. In particular, all the code blocks were just images from the PDF.

Chris Loper at Intelligent English worked very hard to make better eBooks from our original DocBook XML source. This new version has taken a long time to percolate through the system, but it is finally available at Amazon.

If you have the old Kindle book (with the code as images), you can get the new version if you ask for it from Kindle Support. The phrase that pays is “Please send the updated version of iPhone Programming: The Big Nerd Ranch Guide to my Kindle account.”

If you have any bookmarks or notes attached to the old edition, you will lose them when you download the new version. (That’s why Amazon doesn’t automatically push new versions.)

(At this time the purchase of the eBook is completely separate from the purchase of the pBook. There is no discount for buying both.)

Xcode Templates

Update: It appears Apple has done a lot of these things, so thanks!

If you follow me on Twitter, you’ve probably seen my disapproval of the templates that ship with Xcode. Disapproval is a nice way of saying, “The templates are really bad.” So, I have to ask for a favor from everyone. Please submit a bug report to Apple and ask them to change their approach on templates. You can link to this article, copy and paste its contents, or write your own thoughts.

Now, before I point out the bad, I’d like to give my opinion on what a good template should do:

1. A template should minimize keystrokes by adding code you always need and never code you will usually delete.

2. A template can provide simple boiler-plate code for beginning programmers so they can add substance to existing form, without sacrificing rule 1.

3. A template should not make any design or stylistic choices for developers.

I think we can all agree on the first two rules. The third rule is subjective: what is the best design? What is the best style? There isn’t a right answer. Therefore, a template should omit any code that potentially interferes with rule 3. When it doubt, leave it out. Here are two of the worst offenders of these rules:

1. Creating a universal window-based application gives you an abstract superclass for the app delegate, two concrete subclasses of that superclass and two XIB files.

This violates rule 3. There is an alternative design for universal applications that only requires a single application delegate and a single XIB file.

To be honest, this template is very bad. You do not need two MainWindow XIB files. You can have a single XIB file with a window and an app delegate. Check the box that says “Full Screen at Launch.” With this flag set, no matter what device you are on, the window is the right size. You don’t need three app delegates either, here’s an example of a single app delegate that works on both devices:

- (BOOL)application:(UIApplication *)app
  didFinishLaunchingWithOptions:(NSDictionary *)opts
{
    UIViewController *rootMaster = ...;
    if([[UIDevice currentDevice] userInterfaceIdiom] ==
              UIUserInterfaceIdiomPad)
    {
        UISplitViewController *svc = ...;
        ...

        [window setRootViewController:svc];
    }
    else
    {
        UINavigationController *nvc = ...;
        ...

        [window setRootViewController:nvc];
    }

    [window makeKeyAndVisible];
    return YES;
}

Not only do you not need the multiple app delegate/XIB monster, I would argue you don’t want it either. Why? Where you once had 3 files to maintain (AppDelegate.h, AppDelegate.m, MainWindow.xib), you now have eight. Instead of one class to write your code in, you have three. Adding complexity like this when you can make a very simple if statement in places where the behavior differs seems like a better choice, right?

2. The UITableViewController has code completion tags in it.

This breaks rule 1. Why? When I create a table view controller subclass, there are plenty of things I need to do before I write the data source methods. In other words, I need to write out the model objects that will be presented by the view object.

The code completion placeholders prevent building the application from being built while doing this. Thus, I must replace those placeholders with “return 0;” right away so I can check my work on those model objects as I write. This is extra work that could easily be avoided by just putting a return 0 in there in the first place.

Now, for rule 2: the errors generated by not replacing the completion handlers are not easy for a beginner to figure out. This hurts them more than helps: they have to type code there anyway, let them figure it out without introducing more issues to fix.

These are the two huge ones. There are other smaller ones that I will just list. (Some of these were introduced in [redacted], so my pretext is, “If you’re thinking about or have already done this, don’t do it…”)

3. Don’t put a label that says “My Universal View Controller” on the window in MainWindow.xib. That doesn’t even deserve my rationale.

4. Ivars are by default protected. Placing a @private at the top of every interface ivar block effectively makes the default private. Developers should opt-in to non-default behavior, not have to opt-out.

5. The app delegate doesn’t need to expose the window as a property; there are other ways of getting the window. I find that using the app delegate as an object dispenser to be very poor design – if someone chooses another design, they can add the property on top of an existing ivar.

6. The code doesn’t need to be chalked with comments. Experienced developers just delete it. For beginners, Apple has a fantastic documentation viewer and great content. Beginners need to learn to use that documentation instead of relying on commented cookie cutter code, or else they will never be able to expand their knowledge.

7. If you’re going to add applicationWillTerminate: as a stub to the app delegate, applicationDidEnterBackground: better be in there, too.

8. Every method that could potentially be overridden or implemented does not need to be stubbed in the templates. viewWillAppear:, viewDidAppear:, the rest of the app delegate methods, etc. We know how to write code, we’ll implement those if we need them. Put the necessary stuff in there.

Overall, I wish they would keep it simple. If a developer wants to customize their own templates, then there should be tools for doing that. (In Xcode 3, this is almost simple. In [redacted] 4, it is very difficult. I spent two hours trying to make you guys some better templates; it did not go well. However, the form of those templates leaves me hopeful that there may be a tool in the future…)

This may seem like a bit much for something so small. And you’re right, it is a small amount of time each developer spends correcting the issues. But it still is an amount of time that could be used more productively.

However, I have an ulterior motive. The templates have caused lots of issues for our students and readers. So much so that the next edition of the book will most likely not use anything but the NSObject template. This is either a lot of extra typing or a lot of explanation to the reader for something that they shouldn’t really worry about. (Imagine if, everytime we told you to create a new class, we had to preface it with a 1/2 page of text showing where to delete code from.)

The templates have become cumbersome instead of helpful. Let’s fix that. Here is my compromise: give us some very simple templates that follow these rules in one category of the left hand table, and some “learning” or highly bloated templates in another category in the left hand table. Everyone is happy!

(You can submit a bug report by going here, logging in with your Apple ID and selecting New Problem. Then, fill out the Problem Report Title to be Xcode Templates. Product: Developers Tools. Version/Build Number: 4. Classification: Enhancement. In the details, just fill out the Summary: with a link to this blog post and a quick summary of the issue.)

Ask Big Nerd Ranch

Let’s face it. We all have questions. Why is the sky blue? What shirt will I wear today? Why does mommy spend so much time on the phone with “the handyman?” Thanks to the Big Nerd Ranch, there is now a place to ask these questions, and more.

OK, truthfully speaking, you should really consider asking us questions about programming in Cocoa or Cocoa Touch. You know, for the Mac, or the iPhone, or the iPad. Do not ask us about your wireless router problems, please.

We’ve teamed up with the fine folks at InformIT to bring you an ongoing series where we answer the best of these questions. We’ve been doing it since February! Go ahead, ask us something!

Here’s a summary of the posts thus far…
Read more »

BNRPersistence

I just open sourced a simple persistence layer for Cocoa and iPhone that uses Tokyo Cabinet. If you are frustrated with Core Data, you might find it useful. Check it out on GitHub.

Here is the Readme:

After a few years of whining that Core Data could have been better, I thought I should write a persistence framework that points in what I think is the right direction. And this is it.

One big difference? Objects can have ordered relationships. For example, a playlist of songs is an ordered collection. This is awkward to do in Core Data because it uses a relational database.

Another big difference? It doesn’t use SQLite, but rather a key-value store called Tokyo Cabinet.

BNRPersistence is not really a framework at the moment, just a set of classes that you can include in your project.

Install

First, you need to download Tokyo Cabinet:
http://1978th.net/tokyocabinet/
(There is a sourceforge page, but the latest build seems to be on this site.)

In Terminal.app, untar the tarball and cd into the resulting directory.

(You want 64-bit library? In Terminal, set an environment variable for 64-bit builds:

export CFLAGS='-arch x86_64'

)

Configure, build, and install:

./configure
make
sudo make install

Now, you have a /usr/local/lib/usr/local/lib/libtokyocabinet.a that needs to linked into any project that uses these classes. (I usually use the “Add->Existing Frameworks” menu item to do this.)

You’ll also need to have /usr/local/include/ among your header search path. (See the Xcode target’s build info to add this.)

Now just add the classes in the BNRPersistence directory into your project. (If you copy them, you won’t get the new version when you update your git repository. This may be exactly what you want, but these are pretty immature, so I would suggest that you link to them instead.)

Using it

You’ve used Core Data? The BNRStore is analogous to NSManagedObjectContext. BNRStoredObject is analogous to NSManagedObject. There is no model, instead, like archiving, you must have two methods in you BNRStoredObject subclass. Here are the methods from a Playlist class:

- (void)readContentFromBuffer:(BNRDataBuffer *)d
{
    [title release];
    title = [[d readString] retain];

    [songs release];
    songs = [d readArrayOfClass:[Song class]
                     usingStore:[self store]];
    [songs retain];
}

- (void)writeContentToBuffer:(BNRDataBuffer *)d
{
    [d writeString:title];
    [d writeArray:songs ofClass:[Song class]];
}

So, BNRDataBuffers are like NSData, but they have methods for reading and writing different types of data. (It does byte-swapping so you can move the data files from PPC to Intel without a problem.)

(I certainly debate the idea of a model file that would replace these methods, but for now this is fast and simple. If you would rather have a model file than implement these methods, you are invited to write a BNRPersistenceModelEditor.)

All the instances of class will be stored in a single TokyoCabinet file, thus you will be saving to a directory containing one file for each class that you are storing.

To create a store, first you must create a backend. I have tried BerkeleyDB and GDBM, but I am quite enamored with Tokyo Cabinet right now. (If you would like to try the other backends, write me and I’ll send you the necessary classes.)

NSError *error;
NSString *path = @"/tmp/complextest/";
BNRTCBackend *backend = [[BNRTCBackend alloc] initWithPath:path
                                                     error:&error];
if (!backend) {
    NSLog(@"Unable to create database at %@", path);
    …display error here…
}

Now that you have a backend, you can create a store and tell it which classes you are going to be saving or loading:

BNRStore *store = [[BNRStore alloc] init];
[store setBackend:backend];
[backend release];

[store addClass:[Song class]];
[store addClass:[Playlist class]];

(You must add the classes in the same order every time. The classID of a class (see BNRClassMetaData) is determined by the order)

Now to get a list of of the playlists in the store:

NSArray *allPlaylists = [store allObjectsForClass:[Playlist class]];

To insert a new playlist:

Playlist *playlist = [[Playlist alloc] init];
[store insertObject:playlist];

To delete a playlist:

[store deleteObject:playlist];

To update a playlist:

[store willUpdateObject:playlist];
[playlist setTitle:@"CarMusic"];

(Yes, this is a place where a model file would make the framework cooler: I could become an observer of this object and get notified when the value changed.)

(As a side-note, there is some experimental support for automatically updating the undo managed. Just give the store an undo manager. This also could be made better with a model file.)

To save all the changes:

BOOL success = [store saveChanges:&error];
if (!success) {
    NSLog(@"error = %@", [error localizedDescription]);
    return -1;
}

Each class in a store can have a version. This is kept in the BNRClassMetaData object for the class. You can reach this in your readContentFromBuffer method (because you have access to the store).

In your BNRStoredObject class, you can implement these two methods if you wish:

- (void)prepareForDelete;
- (void)dissolveAllRelationships;

prepareForDelete is where you implement your delete rule: When a song is deleted, for example, it needs to remove itself from any playlists it is in.

dissolveAllRelationships is a fix for a common problem. You close the document, but the objects in the document have retain cycles so they don’t get deallocated properly. In dissolveAllRelationships, your stored objects (the ones in memory) are being asked to release any other stored objects they are retaining.

In the directory, you will find TCSpeedTest and CDSpeedTest. These are command-line tools that compare the speed of some tasks in BNRPersistence (TCSpeedTest) and Core Data (CDSpeedTest)

Your mileage may vary, but I see:

Creating 1,000 playlists, 100,000 songs, and 100 songs in each playlist and saving (ComplexInsertTest):
BNRPersistence is 10 times faster than CoreData

Reading in the playlist and getting the title of the first song in each playlist (ComplexFetchTest):
BNRPersistence is 13 times faster than CoreData

Creating 1,000,000 songs and inserting them and saving (SimpleInsertTest):
BNRPersistence is 17 times faster than CoreData

Fetching in 1,000,000 songs (SimpleFetchTest)
CoreData is a little faster than BNRPersistence
(BNRPersistence is single-threaded and CoreData has some clever multi-threading in this case. I think I can do similar tricks in BNRPersistence and catch up in this case. In either case, it is very, very fast. On my machine, fetching a million songs takes 3 seconds the first time and 2 seconds the second time.)

Getting it on the phone

The first problem is that you need to compile TokyoCabinet for arm. I tried every configure trick I could come up with and then just created an Xcode static library project and dumped the source into the project. This project is in the repository.

When you link to the resulting static library, you will also need to link in libz, which is part of the iPhone SDK

License

My code is under the MIT license and Tokyo Cabinet is under the LGPL. I think this will enable you to use it how you want to use it. If something bad happens because of the code, you can’t sue us. And if you make changes to Tokyo Cabinet, I think you need to submit those changes to the author. But I’m not a lawyer…

To Do

I recognize that there is room for improvement here:

1) The creation of a model-file architecture and editor
2) Add Tokyo Distopia to make full-text search fast
3) Use B+ trees to make attributes indexable
4) Better automatic undo support
5) Automatic syncing to a web service
6) Easy hooks for QuickLook images and Spotlight metadata in BNRStoreDocument
7) Hook it up to Tokyo Tyrant for non-local storage

Core Animation Target-Action Layers

When you write a Core Animation heavy application, you spend a lot of time implementing code that executes when an animation finishes. Typically, the view controller whose view contains the animating layers implements animationDidStop:finished: and does a series of checks to see which animation finished. This method becomes difficult to manage as the number of animations it handles increases. You must also set the delegate of each animation object and tell them not to remove themselves when finished. You end up writing a lot of code over and over again.

It would be simpler to have animations work more like UIControls. A layer would have a set of target-action pairs that would be triggered when an animation it is running completes. That way, you could easily chain animations or have code executed only after an animation completes.

How would you achieve this functionality? You would subclass CALayer. This layer subclass would have a list of target-action pairs for animation keys. (Note: Not animation key paths, but rather the name you assign to an animation when it is added to a layer.) Here is the code for that subclass:

BNRActionLayer.h:

#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>

@interface BNRActionLayer : CALayer {
    NSMutableDictionary *targetActionPairs;
}
- (void)addTarget:(id)t action:(SEL)a forKey:(NSString *)k;
- (void)removeTarget:(id)t action:(SEL)a forKey:(NSString *)k;
- (NSArray *)actionsForTarget:(id)t forKey:(NSString *)k;
@end

BNRActionLayer.m:

#import "BNRActionLayer.h"

// Declare a private class to keep track of target-action pairs
@interface BNRActionLayerTargetActionPair : NSObject
{
    id target;
    SEL action;
}
@property (nonatomic, assign) id target;
@property (nonatomic, assign) SEL action;
@end

@implementation BNRActionLayerTargetActionPair
@synthesize target, action;
@end

@interface BNRActionLayer (Private)
- (NSMutableArray *)pairsForKey:(NSString *)k;
@end

@implementation BNRActionLayer
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
    for(NSString *observedKey in targetActionPairs) {
        if([self animationForKey:observedKey] == theAnimation) {
            NSArray *pairs = [self pairsForKey:observedKey];
            [self removeAnimationForKey:observedKey];
            for(BNRActionLayerTargetActionPair *pair in pairs) {
                if(flag)
                    [[pair target] performSelector:[pair action]
                                        withObject:self];
            }
        }
    }
}
- (void)addAnimation:(CAAnimation *)theAnimation forKey:(NSString *)key
{
    NSArray *targetActionsForThisKey = [targetActionPairs objectForKey:key];
    if([targetActionsForThisKey count] > 0) {
        [theAnimation setRemovedOnCompletion:NO];
        [theAnimation setDelegate:self];
    }
    [super addAnimation:theAnimation forKey:key];
}
- (void)addTarget:(id)t action:(SEL)a forKey:(NSString *)k
{
    if(!targetActionPairs)
        targetActionPairs = [[NSMutableDictionary alloc] init];

    NSMutableArray *pairsForKey = [self pairsForKey:k];
    if(!pairsForKey) {
        pairsForKey = [NSMutableArray array];
        [targetActionPairs setObject:pairsForKey forKey:k];
    }

    for(BNRActionLayerTargetActionPair *pair in pairsForKey) {
        if([pair target] == t && [pair action] == a)
        return;
    }

    BNRActionLayerTargetActionPair *newPair =
        [[BNRActionLayerTargetActionPair alloc] init];
    [newPair setTarget:t];
    [newPair setAction:a];
    [pairsForKey addObject:newPair];
    [newPair release];
}
- (void)removeTarget:(id)t action:(SEL)a forKey:(NSString *)k
{
    NSMutableArray *pairsForKey = [self pairsForKey:k];
    if(!pairsForKey)
		return;

    BNRActionLayerTargetActionPair *removablePair = nil;
    for(BNRActionLayerTargetActionPair *pair in pairsForKey) {
        if([pair target] == t && [pair action] == a) {
            removablePair = pair;
            break;
        }
    }
    [pairsForKey removeObject:removablePair];
}
- (NSMutableArray *)pairsForKey:(NSString *)k
{
    return [targetActionPairs objectForKey:k];
}
- (NSArray *)actionsForTarget:(id)t forKey:(NSString *)k
{
    NSMutableArray *list = [NSMutableArray array];
    NSMutableArray *pairsForKey = [self pairsForKey:k];
    for(BNRActionLayerTargetActionPair *pair in pairsForKey) {
        if([pair target] == t)
            [list addObject:NSStringFromSelector([pair action])];
    }
    return [NSArray arrayWithArray:list];
}
- (void)dealloc
{
    [targetActionPairs release];
    [super dealloc];
}
@end

How do you use this class? In your view subclass, make sure the type of layer it uses is of type BNRActionLayer (if you are using an explicit layer, you would simply create an instance of BNRActionLayer):

@implementation MyView
+ (Class)layerClass
{
    return [BNRActionLayer class];
}
@end

When you create an instance of MyView, you can add target-action pairs to it.

- (void)applicationDidFinishLaunching:(UIApplication *)app
{
    MyView *v = [[[MyView alloc] initWithFrame:someRect] autorelease];
    [window addSubview:v];
    [(BNRActionLayer *)[v layer] addTarget:self
                                    action:@selector(viewDidFadeIn:)
                                    forKey:@"Fade In"];

    [window makeKeyAndVisible];
}

Of course, you then need to implement viewDidFadeIn: to do something. Let’s pretend you are fading a view so it can become touchable:

- (void)viewDidFadeIn:(BNRActionLayer *)layer
{
    // We can operate on the layer here, do some controllery stuff, and we
    // can also get the this layers owning view. An implicit layer's delegate
    // is always its view (on the iPhone).
    MyView *v = [layer delegate];
    [v setUserInteractionEnabled:YES];
}

So, how would you create an animation that will trigger this message to be sent when it finishes? The same way as you would normally create an animation:

- (void)activateView:(MyView *)v
{
    CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"opacity"];
    [a setToValue:[NSNumber numberWithFloat:1]];
    [a setDuration:1];

    // The key here matches the key the target-action pair was added for
    [[v layer] addAnimation:a forKey:@"Fade In"];
}

Cool, huh? Disclaimer: I’ve been using this code for a few days and it hasn’t given me any problems. However, that doesn’t mean it is perfect. This was definitely a wake-up-at-3am-from-a-programming-dream-and-write-code type deal. (I dream about programming. I’m weird.) If you have any suggestions for improving the code or find a problem, by all means, please don’t hesitate to comment.

Furthermore, if your understanding of layers is a bit fuzzy (for example, you did a double-take when I said that a layer’s delegate is always its view), be sure to keep an eye out for the Big Nerd Ranch iPhone book, written by Aaron Hillegass and myself, due early next year.

iPhone Review Process

(Disclaimer: These are my (Joe Conway) opinions. Not Aaron Hillegass’ or any of the rest of the Big Nerd Ranch staff.)

It shouldn’t come as a surprise to the programming community that many developers are upset at Apple’s review process for iPhone applications. In fact, typing “rejected” into my Google bar shows “rejected iphone apps” as a suggestion.

When a high-profile iPhone application gets rejected and the story hits the blogs, there is an uproar: “Apple sucks!” “Switch to Droid!” “It’s all about the money for Apple!” This kind of attitude simply makes me laugh. But, the collective conscious that is the internet is right about one thing, it is all about the money. But not just for Apple, for any business.

A business is a group of employees that provides a service or a product. The money earned from the sale of said service or product is used to pay the employees, cover facility costs, electricity bills, health insurance, buy cleaning products for the office, the list goes on. The revenue generated by the service or product must match or exceed the cost to produce. If the revenue falls short of the cost, employees lose their jobs. A person without a job cannot provide for their family. Therefore, profitable businesses are essential to our survival.

What does this have to do with App Store rejections? Everything. Apple is providing a product (the iPhone) and a service (the App Store) to end-users. Their goal is to earn more money than it costs to create their products and services. To do this, they must survive in a highly competitive market that is growing at an amazing rate. How do you survive in a market like that? By differienating yourself from the competition.

Apple differientiates themselves from competitors by having a consistent and reliable experience. This is why the iPhone is successful. The misunderstanding is who that consistent and reliable experience is for. It is not for developers, it is for consumers. What the nay-saying high-profile developer folk in Silicon Valley have forgotten is that there is a world that exists outside of Northern California. This world is filled with people who don’t understand technology, but still use it everyday. The majority of iPhone users are part of this world – they expect things to “just work.”

The iPhone review process makes sure that these users are satisfied with their product. Now, Facebook developer Joe Hewitt argues that “we have our own product managers and quality assurance testers, and we are liable to our users.” What Mr. Hewitt fails to realize is that he is working for a half-a-billion-dollar corporation with the resources to create high quality applications and test them thoroughly. (Side note: In case you haven’t seen the Facebook iPhone App, do yourself a favor and download it.)

Most iPhone developers are not this well-financed or experienced. When an inexperienced developer writes an application, not only is the application more prone to crashing or not working as intended, the inexperienced developer doesn’t know how to test for these problems properly. If Apple let every application in to the App Store as-is, I would wager that an incredible amount of applications would crash, freeze or generally give the user a bad experience.

The majority of the blame for a poor user experience would fall on Apple. And this is what angry developers are failing to realize: the typical user of an iPhone does not differentiate between Apple and the companies that write software for the iPhone. If a user purchases applications, and the applications crash or don’t work, they are going to be upset at the iPhone, not at the companies or individuals that wrote the applications.

Consider what might happen if Apple allowed Flash web apps to be executed in Mobile Safari. We all know Flash is slow and it crashes Desktop Safari like clockwork. If Flash web apps were allowed on Mobile Safari, Mobile Safari would be slow and it would crash. The end user would not say, “I’m never going to that website again!” They would go to their blog and write, “I like my iPhone, but the web browser is really unstable. I bought this phone to browse the web. I’m switching to (insert next smartphone here).” This would be bad for Apple.

As an iPhone developer, what is bad for Apple and its iPhone is bad for you. If lots of applications typically crashed or did not work, the end user would suffer. If the end user suffers, the iPhone sells less units. If the iPhone sells less units, you, as a developer, make less money because your available market is smaller. The review process is making you money and helping you to be a better programmer. These are good things. (And, without the review process, there would also be even more crap on the App Store.)

Joe Hewitt also argues that “any bug that Apple finds after their two week delay would have been found by users on day one, and fixed on day two.” Yes, maybe by a quality development team working on a high-profile application. However, a less experienced developer team (or developer, singular) may not know how to fix that bug. They may not have a website for users to submit that bug. They may not even know that bug exists because their small userbase has yet to encounter it. It is not in the best interest of iPhone users, iPhone developers or Apple to have unstable applications on the App Store.

Besides all of this, there is still the issue of security. One may argue that the world wide web doesn’t have a review process and it does just fine. I imagine the guys making millions off security software for Windows OS would agree. The iPhone could be another platform they can sell their software on! Could you imagine having to have Norton Anti-Virus on your iPhone? (You could also argue that sandboxed applications make the iPhone safe. Someone will always find a way to bypass security measures. The review process helps to prevent that.)

So, what is the point? You should concentrate on doing the hard work required to excel. You should read the documentation, learn proper memory management and learn better programming practices that ensure your application is stable. Occasionally, you might get thrown a rejection curveball by Apple. You should work through the problem instead of giving up and threatening to switch platforms.

How to Time

I was asked three times last week how I find how long an activity takes on the Mac and the iPhone.  Here is the most accurate method that I know of:

#import <mach/mach_time.h>

uint64_t start = mach_absolute_time();

// do stuff to be timed

uint64_t end = mach_absolute_time();
uint64_t elapsed = end - start;

mach_timebase_info_data_t info;
if (mach_timebase_info (&info) != KERN_SUCCESS) {
    printf ("mach_timebase_info failed\n");
}

uint64_t nanosecs = elapsed * info.numer / info.denom;
uint64_t millisecs = nanosecs / 1000000;

As you use this, remember that the elapsed time for a given function will vary with the load the system is under.

Real iPhone Crap 3: Where’s the @override keyword?

This one is not really crap; it is just a sad omission in the Objective-C 2 language.

I spend a lot of time debugging other people’s code, and a surprisingly common error is a misspelled delegate or datasource method. Often I’ll see a method like this:

- (NSInteger)numberOfSectionsInTableview:(UITableView *)tv
{ ... }

And I’ll stare at the method for 15 minutes trying to figure out why the method isn’t getting called. (The “v” should be uppercase.)

With Objective-C 2, Apple did something great: The @optional tag on protocols. Now the delegate or datasource method could be declared properly in a protocol:

@protocol UITableViewDataSource <NSObject>
@optional
...
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tv;

And I can specify that my class is a table view data source by declaring that it conforms to the protocol:

@interface CrapController : UIViewController <UITableViewDataSource>

But, there is still no way to get the compiler to catch my misspelled data source method.

Our lives would be better if we had an @override keyword that would say to the compiler “The next method is previously declared in the header file of one of my ancestors or in one of the protocols that I conform to.” If the compiler couldn’t find the declaration, it would give you a stern warning. This code, for example, would generate such a warning:

@override
- (NSInteger)numberOfSectionsInTableview:(UITableView *)tv
{ ... }

A small check like this, combined with the new optional protocols, would make a whole class of errors obvious at compile time rather than at run time.

(Yes, I’ve suggested this to the compiler guys at Apple. Perhaps this posting will help it become part of the collective unconscious that will form Objective-C 3.)

Xcode Templates

Aaron Hillegass’ last post on initializers for UIViewController was spot-on. In fact, when you come to our iPhone Bootcamp, you’ll learn all about it.

However, the extra typing every time we create a file is a nuisance. When you create a subclass of a UIViewController, chances are you really want to get to work on the important stuff. In this post, I’ll show you how to set up your Xcode template for UIViewController subclasses with a XIB file so that you don’t have waste any time creating your next iPhone app.

Currently, Xcode templates are located at:

/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/

(I say currently because there is no guarantee the next major version of Xcode will look for templates there. You are safe for now, though.)

What we want to do is change the template for creating UIViewController subclasses. That template is located here:

/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/File Templates/Cocoa Touch Class/UIViewController subclass

Quick Finder Tip: When the Finder is active, hit Cmd-Shift-G. Copy and paste the previous path in to the sheet that appears and hit Go. If you installed the Developer tools to another directory, you’ll have to replace /Developer/ with that path. Optionally, you can spotlight for FILEBASENAMEASIDENTIFIER and it will point you within the vicinity. (FILEBASENAMEASIDENTIFIER is the keyword in Xcode templates that gets replaced by the name of the file you are prompted to enter.)

In this directory, there is a property list and two directories. (For the more curious, you can open up the property list for some interesting Xcode hacking.) The directory we are interested in is UIViewController subclass with XIB.pbfiletemplate. Open that directory.

From that directory, open class.m in Xcode. Mine looks like the following:

//
//  «FILENAME»
//  «PROJECTNAME»
//
//  Created by «FULLUSERNAME» on «DATE».
//  Copyright «YEAR» «ORGANIZATIONNAME». All rights reserved.
//

«OPTIONALHEADERIMPORTLINE»

@implementation «FILEBASENAMEASIDENTIFIER»

- (id)init
{
    self = [super initWithNibName:@"«FILEBASENAMEASIDENTIFIER»"
                           bundle:nil];
    // Initialize ivars not related to [self view] or XIB objects

    return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil
               bundle:(NSBundle *)nibBundleOrNil
{
    return [self init];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Init ivars that need anything from the XIB or [self view]
}

- (void)viewDidUnload
{

}

- (void)dealloc
{
    [super dealloc];
}

@end

You can copy and paste this text in to that file and save it or roll your own. Now you can imbibe Aaron’s wisdom without having to do any real work!

Real iPhone Crap 2: initWithNibName:bundle: is the designated initializer of UIViewController

Before I go into another shortcoming of UIKit, I’d like to make it plain that I genuinely like most of UIKit. In many ways it is much better than AppKit. I love UIControl, and I think that UITableViewCell being a subclass of UIView is a huge step forward. But, the weaknesses are the parts that demand difficult design decisions, so I’m delving upon them in this series.


Like UIViewController, NSDocument was designed to be subclassed. They both can also load a nib file. Let’s look at how NSDocument does it.

The designated initializer of NSDocument is init. How then, does the subclasser specify the nib file to load? He implements windowNibName:

- (NSString *)windowNibName
{
    return @"CrapDocumentNib";
}

What is cool about this?

  • The name of the nib file is in exactly one place — inside the controller class that will be using the nib file
  • The NSDocument subclass and its nib file become a module that can be easily reused in other applications
  • Classes that use the NSDocument subclass don’t need to know anything about the nib file or whether it uses a nib file at all

In short, this design means that we can reap all the benefits of object encapsulation.

The designers of UIViewController, on the other hand, decided to make the designated initializer:

 - (id)initWithNibName:(NSString *)n bundle:(NSBundle *)b;

(I suspect that this had something to do with making it possible to specify the nib file inside Interface Builder:

“Gosh, Wally, that’s going to make for a great demo!”)

If you make initWithNibName:bundle: the initializer for your UIViewController subclass, wherever you create an instance, you must specify which nib file goes with it:

CrapViewController *cvc;
cvc = [[CrapViewController alloc] initWithNibName:@"CrapViewNib"
                                           bundle:nil];

This makes no sense: the name of the nib file should be in one place, and that place should be inside CrapViewController.m. I see most developers putting the name of the nib file in a dazzling array of places: in code wherever the view controller is created and in nib files where view controllers are created.

Stylish iPhone programmers, however, are changing the designated initializer of their UIViewController subclass to init:

- (id)init
{
    [super initWithNibName:@"CrapViewNib" bundle:nil];
    … give ivars initial values…
    return self;
}

Now being a fastidious Objective-C programmer, you must also override the designed initializer of the superclass to call your designated initializer:

- (id)initWithNibName:(NSString *)n bundle:(NSBundle *)b
{
    return [self init];
}

Voila! The benefits of object encapsulation are restored to your application:

CrapViewController *cvc = [[CrapViewController alloc] init];

(Can I mention that I, personally, don’t instantiate view controllers in nib files. Many of my view controllers act as the owner of nib files, but I always create the view controller itself programmatically. I don’t have a great argument for this, but I do find it easier to understand the work of developers who follow this guideline.)

Before I close this, I’d like to you to imagine how much easier it would have been if the UIViewController had followed the design of NSDocument. When you opened up any UIViewController subclass you would immediately look for the viewNibName method:

- (NSString *)viewNibName
{
    return @"CrapViewNib";
}

Now you know which nib file goes with the view controller. If the method returns nil, you would know that the view controller doesn’t use a nib file. If the method didn’t exist at all, you would know that the nib file’s name was the same as the class name.

Instead of two init methods, there would be one init method if you needed to initialize some instance variables and none if you didn’t.

And life would be a little bit better.


If you missed the last installment, you might want to read Real iPhone Crap 1.

Real iPhone Crap 1: UINibLoading uses Key-Value Coding

Last week, my colleague Joe Conway wrote a posting suggesting that dot-notation was not a great addition to the Objective-C language and that he felt that programmers should not use it.  There was outrage. I, myself, was shocked that people cared at all.  After all, there are some examples of truly stupid stuff that Apple has done that are being misused in genuinely dangerous ways by the iPhone developer community.  These are worthy of discussion.  So, I’m doing a multi-part feature that I will call “Real iPhone Crap,” and this is the first installment.


On the desktop, when a nib file is loaded, outlets are set in a sensible way: to set an outlet called foo, the nib loader looks for an accessor called setFoo:. If it is unable to find the accessor,  the nib loader sets the variable foo directly.  This sounds like key-value coding, right?  It isn’t.  The important difference is that nib loading treats foo as a weak reference; the object it points to is not retained.

Thus, if you create a subclass of NSViewController that has a dozen outlets to subviews, only the top-level view is retained.  So, when the view controller is deallocated, it releases the top-level view and all the subviews are automatically deallocated.  Tidy!

On the phone, however, the nib loader uses key-value coding to set the outlets; By default, outlets are treated as strong references.  If you don’t have an accessor for your outlet, the view it refers to is retained.

Thus, if you create a subclass of UIViewController that has a dozen outlets to subviews, all of the subviews are retained.  When the view controller is deallocated,  the top-level view is released automatically, but you (in dealloc) still need to explicitly release all the subviews that you have outlets to.

But it is even worse than that on the phone because that top-level view is, by default, released if it is offscreen when a memory warning arrives.  So, the view may be destroyed and recreated many times during the life of the view controller.  You must also explicitly release the retained subviews in viewDidUnload. (OK, I just reread this and realized that the reader might get the idea that the retained views are leaking every time the view is unloaded. It is not quite that bad. A retained view will linger until the view is reloaded. At that point, it will be released as a side-effect of the setValue:forKey: that gets called when the outlet is set again.)

The use of key-value coding in nib loading is idiotic.  (Way more idiotic than dot-notation.)  There was a way that worked fine for 15 years, and Apple loused it up.  This stupidity and the developer community’s misunderstanding of it is the largest source of memory leaks on the phone.

There are two possible ways to fix this memory leak:

  • Release all your outlets in dealloc and viewDidUnload (Make sure you set them to nil in viewDidUnload.)
  • Make your outlets weak references

I haven’t seen many programmers using the second option, so let me be more explicit.  If you have an outlet called crapButton, declare it thusly:

@interface CrapViewController : UIViewController
{
    IBOutlet UIButton *crapButton;
}
@property (nonatomic, assign) IBOutlet UIButton *crapButton;

Then, in CrapViewController.m:

@synthesize crapButton;

Now that button is not being retained. (You will need to be sure that view is loaded before you can send any messages to this button.)

One of the nice things about not being an Apple employee anymore, is that I can tell my students honestly: “This is crap, and this is the way we work around it.” I hope this series proves useful to those who have not been able to attend our Beginning iPhone Bootcamp (for beginning programmers) or our iPhone Bootcamp (for experienced programmers).

Dot-notation Syntax

When I teach, I always make sure to mention the dot-notation addition to Objective-C 2.0. Then, I make sure to tell the students never to use it ever, ever, ever again. But why? Why this seemingly irrational hatred of dot-notation? Is this a style choice and us “bracketeers” are being hard-headed? The answer is no, we are not being hard-headed, we are keeping our code consistent and maintaining readability.

The Intent of Code

The naming conventions used in Cocoa and Cocoa Touch are clear and straightforward. When we look at well written Mac or iPhone code, we can tell exactly what is going on by glancing at it. That’s the power that Objective-C gives us. If I want an object to take a drink of water while doing a cartwheel, I send it the message:

    [obj takeDrinkOfLiquid:water whileDoingCartwheel:YES];

We know exactly what that means. There is no room for interpretation. Likewise, we know exactly what this line of code does:

    a = b + 5;


This adds b and the value 5 together and assigns the result to the variable a. We get these operators, = and +, from the C programming language. We have a lot more operators in C, like *, /, -, % and &. And we know what all of those operators mean. When we see them, we say stuff like, “That’s a division!” or “That’s a subtraction!” Except we don’t say that. We don’t even think about that. We instantly know.

Another operator that is commonly used in C is the . operator. The dot operator accesses a member of a structure. It goes to an address in memory (the address of the structure object) plus an offset. That’s all it does. We instantly know what it means.

Sometimes, an operator may have another meaning depending on the context. For example, the * operator could be dereferencing a pointer or it could be doing a multiplication. However, the context this operator is being used in allows us to easily discern which operation is occuring. The dereferencing * is a unary operator and the multiplication * is binary operator. When we look at code, we know which one is being used.

    int a = *ptr; // Definitely a dereference!
    int c = a * b; // Definitely a multiplication!
    int c = a * (*b); // Definitely both!

In Objective-C, the square brackets ([]) were added for message sending. While the square brackets had previously only been used for indexing an array, the intent of the brackets can be easily determined by the context.

    [object message]; // Definitely a message send!
    int a = variable[index]; // Definitely indexing!

With that, we can say that we definitely know what the operators in Objective-C do with a quick look.

Then comes Objective-C 2.0…

With Objective-C 2.0, we get dot-notation. Many programmers new to Objective-C like dot-notation, it reminds them of other languages that they are more proficient in. Except for dot notation doesn’t do the same thing in Objective-C as it does in other languages.

Dot-notation in Objective-C invokes an instance method. Code in a method definition is executed when this dot is used. This code could be simple and it could just return a value. That doesn’t cause much of a problem. However, what if that method is a lot beefier:

- (int)value
{
    NSData *valueWrapper = [NSURLConnection sendSynchronousRequest:...];
    if(valueWrapper)
    {
        const int *v = [valueWrapper bytes];
        return *v;
    }
    return -1;
}


That method could go wrong in a number of ways. When we see the invocation of that method with dot-notation, all we see is:

    int x = foo.value;


What does that mean? Are we getting the value field out of the structure object foo? Are we executing a simple method that returns a value? Or, in this case, are we creating a network connection, pulling a value from a web server, turning that data in to an integer and then returning it?

It is ambiguous. With dot-notation, we don’t know exactly what this code means at first glance. When we see this code:

    int x = [foo value];


Our first glance tells us we are definitely sending a message. That clues us in that more work is being done, not just a simple memory offset and an assignment.

What is more confusing, especially to Objective-C newcomers, is invoking a setter method with dot-notation.

    foo.object = otherObject;

In C or C++, this is a simple assignment. In Objective-C, this could easily be creating a copy of otherObject or retaining otherObject. It is not immediately apparent from that line of code. The difficulty of understanding reference counting as a beginner gets amplified by code like this. Our code takes longer to read. We have to dig around to determine what is actually happening in this line of code.

Same context, same operator, different operation. We don’t know what this operator does anymore.

Return Values

Here is another example:

    someView.frame.size.width = 30;

Very straightforward, we’re setting the width of a view’s frame to 30 pixels.

Actually, no. We are not. We’re generating a compiler error. The value returned by a dot-notation invocation is not an lvalue. We can’t assign it anything. However, if someView is a structure, that line of code will work as intended.

    someView.frame.size.width = 30; // This is valid code!

We lose consistency in our code using the dot operator. An operator in the same context, one is valid code, one is not. (It’s also a good thing that first line generates a compiler error, otherwise, we’d only be changing the copy of someView‘s frame, not the instance variable of someView.)

Now, that is confusing.

But I’m used to C#, C++, Java. Dot-notation looks like I’m at home!

You aren’t at home. You’re working with another language.

If one language solved all problems, everyone would use that language. Each language and API is a tool and it has an intended use. Using dot-notation in Objective-C would be akin to pounding nails in with a screwdriver. Sure, it works most of the time, but it isn’t the best use of a screwdriver or the best way to hammer nails. Eventually, you might smash your own hand.

Users of dot-notation are typically new to Objective-C. This is most likely the intention of dot-notation; a more familiar syntax for programmers coming from other languages. However, you would be better off familiarizing yourself with Objective-C then pretending it is another language. You will spend less time confused and more time solving a bigger problem.

Apple uses it in their sample code, though!

That’s right, they do. Now, despite what the kool-aid is making you think, Apple does occasionally get something wrong. Their sample code has always been hastily crafted to get developers to use their platform. It is not always the best example of how to use a language.

It is my belief, after teaching roughly 300 students Objective-C, that dot-notation is confusing. It hinders the main goal of software development: writing maintainable, effective, efficient, easy to read and bug-free code.

In the end, there is wrong way and a right way to write Objective-C code. I will not say that using dot-notation is the wrong way. It is an acceptable way to write Objective-C code. I will, however, say there is a better way to write your code. The better way does not include dot-notation.

Find Us at WWDC

As you probably already know, this week marks Apple’s WWDC 2009 Conference in sunny San Francisco, California.

Like all good Apple nerds, several of us from the Big Nerd Ranch will be attending, and we’d love to see you there. Look for Juan Pablo Claude, Joe Conway, Gautam Godse, Brian Hardy, Scott Ritchie and Alex Silverman sporting jaunty cowboy hats wherever they go. If there is some annoying jerk blocking your view of the keynote with their chapeau, it’s probably one of us!

I imagine the scene will look something like the below (actual hats may differ). See you at WWDC!

Nerds In Hats

Get Your WWDC sessions into iCal or Google Calendar

Update: Apple has since removed the date and time information from the JSON data. This code will no longer work. It was fun while it lasted, no?

For those of you attending this year’s sold-out WWDC conference in San Francisco, choosing which sessions to attend can be a daunting task. It’s especially daunting considering that Apple still hasn’t officially announced the schedule for these sessions.

Fortunately, Apple was kind enough to format the session data as JSON (available here) and in this trove of data are dates and times for all of the sessions. Thanks to a tip from the excellent Jeff LaMarche, we can process the data and format it in a more calendar-friendly way.

Jeff’s post uses Ruby to format the data in HTML, which is fine for viewing, but not so good for integration with anything else. I decided to run with that theme and convert the code to output an iCalendar format containing all of the session data. Using this script, you can redirect the output to a file and then import that file into Apple’s iCal, Google Calendar, or whatever other client you fancy.

To run this script, you’ll need to install a couple of Ruby gems if you don’t already have them, like so:

$ sudo gem install json icalendar

Once you have those installed (the above instructions work well on most Unix-like systems), you can then run the following script to generate the iCalendar output. Redirect it to a file called, for example, wwdc_sessions_2009.ics, and you can then import that file into your calendar application.

This code is licensed under the public domain, so use it freely. In case the following does not show up well for you, here is a version in Pastie.

Disclaimer: these times have not been officially announced, so the Big Nerd Ranch takes no responsibility for you missing your favorite session or otherwise imperiling your WWDC experience. You’ve been warned.

require 'rubygems'
require 'open-uri'
require 'json'
require 'icalendar'

sessions_data = JSON.parse(open("http://developer.apple.com/wwdc/data/sessions.json").read)["SessionsData"]

calendar = Icalendar::Calendar.new

sessions_data.each do |session|
  calendar.event do
    dtstart DateTime.parse(session["time"][0]["lower"]).new_offset(-7.0/24)
    dtend DateTime.parse(session["time"][0]["upper"]).new_offset(-7.0/24)
    summary session["title"]
    description session["description"]
    location session["room"]
    categories ((session["focus"] || []) << session["level"] << session["type"]).compact.uniq
  end
end

puts calendar.to_ical

Aaron Hillegass on the Cocoa Text System

As a preview of our Cocoa 2 Bootcamp, I did a presentation on the Cocoa Text System for the Atlanta CocoaHeads. Here is the video and sample code.

Good iPhone Practices

The iPhone SDK has now been around long enough where we can start to pick out good practices in using some of the more “fuzzy” areas. There are two small, but important, practices that can make your life much easier.

Buttons in UITableViewCells

Sometimes, you will want to have a button or some sort of control in a UITableViewCell subclass. You could have many rows, and each one has a button, and that button should have a different result depending on what row it is in.

In sticking with the MVC paradigm, how do you accomplish this? You have to be able to set the target-action pair for these buttons and you also have to decide which row’s button was pressed.

Well, you don’t even have to look at the UITableViewCell, you are really only concerned with the button. A UIButton (or any UIControl) is a subclass of UIView. Every UIView has an integer instance variable called tag. You can use this tag to specify the row the button is currently in.

1. When a UITableViewCell is created (and only when it is created), you add a target-action pair from you UIButton to your UIViewController subclass to call the method you want.
2. When a UITableViewCell’s data is prepared, you set the tag of its button to the row that cell is occupying.
3. When the action message of your UIButton is sent to your UIViewController subclass, you simply grab the tag of the sender to determine what row it is.

Your UITableViewCell subclass interface should look like this:

@interface ButtonCell : UITableViewCell
{
    UIButton *button;
}
@property (readonly) UIButton *button;
@end

And your cell retrieval method should look like this:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ButtonCell *aCell = (ButtonCell *)[tableView
            dequeueReusableCellWithIdentifier:@"ButtonCell"];

    if(!aCell)
    {
        aCell = [[[ButtonCell alloc] initWithFrame:CGRectZero
                                   reuseIdentifier:@"ButtonCell"]
                                        autorelease];
        [[aCell button] addTarget:self
                           action:@selector(buttonPressed:)
                 forControlEvents:UIControlEventTouchUpInside];
    }

    [[aCell button] setTag:[indexPath row]];

    return aCell;
}


And finally, your action message should do this:

- (void)buttonPressed:(id)sender
{
    int rowOfButton = [sender tag];
    [[internalData objectAtIndex:rowOfButton] performFunStuff];
}

All there is to it.

Instantiating UIViewController subclasses

XIB files are confusing. Chaining UIViewController XIB files and creating instances of them in another XIB file is even more confusing. And quite pointless. There is a much better way to do it.

First, you have to decide if you want to use a XIB file or not. The *only* reason to use a XIB file is if you have a complicated user interface that needs to be set up via Interface Builder. Otherwise, if you have a single view like a UITableView, UIImageView or UIView, simply implement loadView.

Now, regardless of how you are creating the interface, all UIViewController subclasses (save the standard ones, like UITableViewController, UINavigationController and UITabBarController) should be instantiated in code and sent an init message.

ViewControllerSubclass *vcs = [[ViewControllerSubclass alloc] init];

You are probably wondering, “Uhh… if I just send it init, how do I load its view from a XIB?” Good question. You will be overriding the init method of your UIViewController subclass (and overriding the superclasses designated initializer).

- (id)init
{
    return [super initWithNibName:@"ViewControllerSubclass" bundle:nil];
}
- (id)initWithNibName:(NSString *)name bundle:(NSBundle *)bundle
{
   return [self init];
}

How does this work out in code? Let’s pretend you have two UIViewController subclasses, RootViewController and DetailViewController. They are both intended to be part of a UINavigationController.

In your application delegate, you should be doing this:

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
    RootViewController *rootViewController =
        [[RootViewController alloc] init];
    UINavigationController *navController = [[UINavigationController alloc]
            initWithRootViewController:rootViewController];

    [window addSubview:[navController view]];
    [window makeKeyAndVisible];
}

In RootViewController’s implementation, you can do a little something like this:

- (void)viewDidLoad
{
    if(!detailViewController)
        detailViewController = [[DetailViewController alloc] init];
}

Therefore, none of your other classes need to know anything about any other UIViewController subclass. They just know if they want an instance of it – with a fully configured user interface – they can just send it init.

Easy enough.

Scott Ritchie works for us!

Big Nerd Ranch has a reputation for mind-blowingly excellent Cocoa and iPhone training. A reputation like this is difficult to maintain. In particular, our students expect our instructors to be experienced, friendly, knowledgeable, articulate, and committed.

For the last seven years, I have taught every single Cocoa class that has ever been offered at Big Nerd Ranch. For a few years, I have felt that only one other person who could possibly fill my shoes at the front of the classroom, and he worked for Apple.

Today, he works for Big Nerd Ranch.

Scott Ritchie started at NeXT in 1990. He has spent the last 20 years helping developers learn to use Objective-C and Cocoa, both as a trainer and as an engineer on Apple’s Developer Technical Support team.

I’ve known Scott for fifteen years, and I must admit that he knows Cocoa better than I do. And he knows iPhone development better than anyone. He is passionate about teaching and committed to making our students into effective and stylish Cocoa programmers. I am proud to announce that he will be teaching the Cocoa Bootcamp and the iPhone Bootcamp for us.

If you would like Scott Ritchie to teach a Cocoa or iPhone Dev class at your company, please contact Scott Newman at (813) 749-6615 so we can get you on the calendar.

Syntax Matters

One of my coworkers, Scott, recently pointed me towards Jacob Kaplan–Moss’s comments on programming languages and thought. In “Syntactic Sugar”, Jacob addresses the canard that “all Turing complete language differ solely on syntactic sugar.” He first concedes that this is technically true, in terms of reduction to machine instructions and register manipulation. At the same time, he says, this view ignores the important effect qualitative differences in the syntactic structure of different programming languages have on the way we as programmers solve problems. In support of this, he introduces the Sapir–Whorf hypothesis from linguistics, which states that, rather than simply being a vehicle for thought, language in fact determines the limits of what is thinkable. He argues that this applies equally to programming languages, and concludes that “we’ll always be more productive in a language that promotes a type of thought with which we’re already familiar.”

Jacob’s initial concession is meant to let him get straight to the point: syntax matters, regardless of whether that syntax is purely “sugar” from the compiler writer’s point of view or not. You could go ahead and look at vocabulary (standard libraries) as well as semantics, but I’d like to look a bit more closely at Jacob’s argument and conclusions.

First off, let me say that I agree with what I see as the most important point of Jacob’s article: Syntax does matter. Unfortunately, I have to disagree with how he gets to that point and the conclusion he draws from it.
Read more »

Django and Django-Template Syntax Highlighting for Coda

I recently started playing with Panic’s web development application, Coda, and I immediately liked its all-in-one approach. As a Django developer, I typically work with multiple text editor, terminal, and browser windows. This can sometimes get out of hand, especially on a laptop. Coda can improve this situation by keeping all these tools and more within a single application.

All of this looked very promising until I realized that Coda does not offer out-of-the-box Django and Django-Template syntax highlighting or autocompletion. Thus, I decided to write a couple of Mode bundles to improve the situation. You may download these bundles and place them in your /Users/username/Library/Application\ Support/Coda/modes directory for instant gratification.

I am still developing these bundles to make them smarter, more lexically complete, and more integrated with Coda. Please let me know about your experience with them and I will try to make them better.

Django.mode.zip

Django-Template.mode.zip