Skip to content

Sad…

image1384260977.jpg

Cupertino is at one edge of the Santa Clara Valley, one of the best places on the continent to grow fruit.

This display is in our Whole Foods, one of the (if not the) largest stores they have. All of the brands are local and don’t exist any more, because we paved them over in favor of single-family homes and office parks and fucking lawns.

It’s really sad, and would have been easy to avoid, too, by building up instead of out. Instead, there are always new ballot measures in Cupertino to try to limit the “scale” of building – in other words, to prevent building up – and ensure the sprawl stays. And I expect that applies to the rest of the Santa Clara Valley as well, and a huge percentage of the United States as a whole, everywhere a “subdivision” has replaced farmland.

Even if we could build high-rise apartments and offices, it’s not certain that the land we’ve covered with little shitbox houses, chemically-maintained lawns, and asphalt could even be used for agriculture again. The land may well be “used up” and require extensive rehabilitation to even support parkland, much less farming.

Someday people will look back on this as a monumental disaster, an utter failure of urban planning ands demonstration of our society’s lack of any capacity for forethought. Probably once all of humanity is facing permanent food and water shortages, later this century.

Milestone

I’ve had my car for 10 years, and my odometer rolled over 100,000 miles earlier today.

Time to start thinking about a new car! Maybe a Tesla Model S, in a couple of years…

Tagged

When to use NSOperation vs. GCD

Mac OS X has a number of concurrency mechanisms, and that increases with Snow Leopard. In addition to run loops, threads (both Cocoa and POSIX) and operations, Snow Leopard adds Grand Central Dispatch (GCD), a very lightweight way to represent units of work and the style of concurrency they need, and have the system figure out how to schedule them.

But wait, don’t we have that already in NSOperation? It shouldn’t surprise you in the least to learn that NSOperation, on Snow Leopard, is built atop GCD. However, there are a number of differences between the two, and for that reason people have started to ask “How should I decide which to use when?”

The straightforward answer is a general guideline for all application development:

Always use the highest-level abstraction available to you, and drop down to lower-level abstractions when measurement shows that they are needed.

In this particular case, it means that when writing Cocoa applications, you should generally be using NSOperation rather than using GCD directly. Not because of a difference in efficiency, but because NSOperation provides a higher-level abstraction atop the mechanisms of GCD.

For example, you can set up a dependency between two NSOperations such that the second will only be run after the first is complete — even if they’re run on different queues. You can use KVO to observe the completion (or cancellation) of different operations — and you can create operations that support being cancelled in the first place. You can set a completion block to run after an application has finished. And you can, of course, create operations from blocks using NSBlockOperation.

You’ll also fit in better with Cocoa by using NSOperation in your high-level code. If you take a look at new Snow Leopard API on NSNotificationCenter, you’ll see one where you specify the NSOperationQueue on which you wish a notification to run a block.

Ultimately, you spend a little bit of overhead to use NSOperation instead of GCD, but you gain significant additional functionality that will be useful as you start to compose operations together. And that’s the biggest benefit of NSOperation: You can break up your application in terms of units of work that can not only be run on a queue, but also canceled, observed, and depended upon. This lets you easily define your data dependencies and ensure that you aren’t simply running code serially as a side-effect of locking.

Tagged , , , , , ,

Welcome to Snow Leopard!

Last week, Mac OS X 10.6 Snow Leopard was released!

Snow Leopard represents a lot of hard work by a lot of folks at Apple and at seeded third-party developers, and it really shows.

Now that it’s shipped, I can actually talk about some of the especially cool things this release has for developers.

Tagged , , , , ,

Rebutting Big Nerd Ranch on Objective-C 2.0 dot notation

The Big Nerd Ranch weblog has a new post about Objective-C 2.0 dot notation. They advocate never using it and they’re completely wrong.

Given my reaction on Twitter, several people have asked me to write a more in-depth rebuttal.

I’ve already addressed when and why you should use Objective-C 2.0 properties and dot notation in an earlier post, so I won’t go into that here. I’ll just repeat my response to their weblog.

Here’s what I wrote in response:

I disagree most emphatically. The whole point of dot notation is that, when combined with properties, it’s not just an alternative syntax for invoking methods. In fact, if that’s how you think about dot syntax, STOP. That’s not what it’s for at all.

What dot syntax and property declarations are for is separating object state from object behavior. Classical OOP only really defines objects as only exposing behavior but the past 30+ years have demonstrated rather aptly that objects consist of both. C# was actually pioneering in this; its concept of properties is rather similar to what the combination of property declarations and dot syntax enable in Objective-C.

To write idiomatic Objective-C 2.0 you should use @property to declare properties, and use dot syntax to access them. Period. Doing otherwise is a bad idea because it will create code that isn’t intention-revealing to other experienced Objective-C 2.0 developers. Teaching students to do otherwise is doing them a disservice, because you’re directly contradicting those responsible for the language and its evolution.

In short, Objective-C 2.0 has properties and dot notation as another way of expressing intent in your code. Use them for that, don’t refuse to use them just because they weren’t in earlier versions of the language, or because they require teaching another concept.

Tagged , , , , ,

Using “en” instead of “English” for your Xcode project’s development region

Various pieces of Mac OS X and iPhone documentation have said for quite a while that the “preferred” method is now to use ISO-639-1 (two-letter) or ISO-639-2 (three-letter) language codes codes for localization purposes. Out of the box, Xcode’s project templates still use “English” rather than “en” as their default localization.

How can you use the ISO-639 language codes everywhere in your project, rather than in just your non-English localizations?

It’s pretty straightforward, but it does require hand-editing of your Xcode project file. This means that before doing anything else, you must quit Xcode and Interface Builder.

The first step is to rename your existing localizable resource directories on disk from English.lproj to en.lproj. You can do it at the Terminal or in the Finder. If you’re using an SCM system such as Subversion, use it to do the renaming so it preserves your file history and such as well.

The next step is to adjust how your existing localizable resources are referenced in your Xcode project file. Open the project.pbxproj file inside your Xcode project in a plain text editor such as TextEdit (rather than Xcode) and replace all but one occurrences of the string English with the string en. The one you don’t want to replace is in a property under the PBXProject section named knownRegions: This is an array of localizations Xcode knows about. Just make sure en is at the end of the array:

knownRegions = (
    English,
    Japanese,
    French,
    German,
    en,
);

At this point, this should be the only place English appears in your project.pbxproj file.

Finally — and this is the important step, and non-discoverable step — you need to add a property to the project.pbxproj file to tell Xcode what the Development Region for your project is. Again, this gets put into the PBXProject section before the knownRegions key from above (Xcode will alphabetize the keys when saving your project for you); it should look like this:

developmentRegion = en;

The default value of this key within Xcode is English and Xcode won’t write the key into the project if the default isn’t changed. However, there’s no user interface within Xcode for actually changing this property, making it non-discoverable. Furthermore, if you are changing your project to use en as its default localization, and you don’t change this property, you won’t be able to add new localizations by inspecting your resources. (This is a known issue.)

At this point, you can save your modified project.pbxproj file and open your project again in Xcode. There’s one more thing you’ll have to change, this time in your product’s Info.plist file (or your products’ Info.plist files), before you can get back to work: You need to change the CFBundleDevelopmentRegion property to en rather than English.

Once you’ve made that change, you should safely be able to use your Xcode project normally, adding localized variants of your resources, building and running, and so on, and everything should Just Work — now using modern ISO language codes instead of the English language names!

Tagged , , ,

Unit testing Cocoa user interfaces: Use Check Methods

In the past, I’ve talked about ways to easily write unit tests for Cocoa applications, including tests for user interfaces using target-action and tests for interfaces using Cocoa bindings. There are some strategies you can apply to make writing tests for Cocoa code even easier, though. They’re just straightforward object-oriented programming, but sometimes we can forget that all the techniques you might use in your main code base can also be applied to our test code.

So here’s one trick that you can use in writing tests for Cocoa user interfaces, especially in ways that will make test-driven development easier.

Use a Common Base Class with Check Methods

The first, probably most important thing to do is use your own common base class for your tests. Don’t derive your tests directly from SenTestCase; instead, derive them from your own MyTestCase class that in turn derives from SenTestCase. This gives you a place to put all of the customization that’s appropriate for your project.

Sometimes you might need a series of assertions to verify some particular state. However, that series of assertions will be the same every time you need to verify that state. Or the assertions themselves aren’t very intention revealing so you always wind up putting a comment above them describing what they’re really doing.

Checking Target-Action

A simple example of this is checking a target-action connection in a user interface. Say you have a view controller that presents a collection of objects managed by an array controller. Its view has an Add button that should send -addObject: to the array controller. You might write a test for it like this:

- (void)testAddButtonSendsAddObjectToArrayController {
    STAssertEquals([viewController.addButton target], viewController.arrayController,
        @"The Add button should target the array controller.");
    STAssertEquals([viewController.addButton action], @selector(addObject:),
        @"The Add button should send the -addObject: action.");
}

That’s not too difficult to understand, but it could be made simpler — it could be done in a single assertion. You’d just write a method to check both the target and action at once and then use that method from your test, like this:

// in your test base class...

/*! Tells whether the control sends the action to the target. */
- (BOOL)checkControl:(NSControl *)control
         sendsAction:(SEL)action
            toTarget:(id)target
{
    return ([control action] == action)
        && ([control target] == target);
}

// in the tests specifying the view controller's behavior...

- (void)testAddButtonSendsAddObjectToArrayController {
    STAssertTrue([self checkControl:viewController.addButton
                        sendsAction:@selector(addObject:)
                           toTarget:viewController.arrayController],
        @"The Add button's action should send -addObject: to the array controller.");
}

That makes the intention behind the entire test a lot clearer, and it makes writing the test easier & safer since you can’t (say) forget to check either the target or the action.

It does lose a tiny bit of information: If the test fails, you’ll have to look at your xib file instead of the failure message to determine whether it’s because the target or the action isn’t set as you’ve specified. However, the trade-off in making the test easier to read and write is worth it here.

Checking Outlets

This is even worthwhile for single assertions, such as those you’d use to test that your outlets are connected in the first place. For example, you might initially write a test that your view controller is your table view’s delegate like this:

- (void)testViewControllerIsTableViewDelegate {
    STAssertEquals([viewController.tableView delegate], viewController,
        @"The table view's delegate should be the view controller.");
}

Rewriting it to be more intention-revealing with a simple check method would make it look like this:

// in your test base class...

/*! Tells whether the outlet is connected to the given destination. */
- (BOOL)checkOutlet:(id)outlet connectsTo:(id)destination {
    return outlet == destination;
}

// in the tests specifying the view controller's behavior...

- (void)testViewControllerIsTableViewDelegate {
    STAssertTrue([self checkOutlet:[viewController.tableView delegate]
                        connectsTo:viewController],
        @"The table view's delegate should be the view controller.");
}

You’re not saving any code by writing your test this way — you’re actually writing more — but its complexity has gone down because it requires less effort to see what it’s actually trying to do.

Checking Bindings

This is even worthwhile in situations where you may still need a few extra assertions. For example, Cocoa bindings are specified using a lot more information than just outlets and target-acton connections; you won’t always want to check (and specify the value of) all of it, but you can easily make the common parts clearer.

Going back to our Add button example, as is typical its enabled state should be bound to the array controller’s canAdd property. Writing a test to specify this involves using -infoForBinding: and interpreting the results, which takes a couple lines of code and a couple of assertions:

- (void)testAddButtonEnabledStateIsBoundToArrayControllerCanAdd {
    NSDictionary *bindingInfo = [viewController.addButton infoForBinding:NSEnabledBinding];
    STAssertNotNil(bindingInfo,
        @"The Add button's enabled state should be bound.");

    id observedObject = [bindingInfo objectForKey:NSObservedObjectKey];
    STAssertEquals(observedObject, viewController.arrayController,
        @"The Add button's enabled state should be bound to the array controller.");

    NSString *observedKeyPath = [bindingInfo objectForKey:NSObservedKeyPathKey];
    STAssertEqualObjects(observedKeyPath, @"canAdd",
        @"The Add button's enabled state should be bound through the 'canAdd' key path.");
}

This isn’t too complicated, but it does start to get tedious, especially given that you have to remember to distinguish between STAssertEquals (pointer equality) and STAssertEqualObjects (object equivalence). Let’s put the tedium in one place:

/*! Tells whether the object's binding is connected through the given key path. */
- (BOOL)checkObject:(id)source
         hasBinding:(NSString *)binding
           toObject:(id)destination
            through:(NSString *)keyPath
{
    NSDictionary *bindingInfo = [source infoForBinding:binding];
    id observedObject = [bindingInfo objectForKey:NSObservedObjectKey];
    NSString *observedKeyPath = [bindingInfo objectForKey:NSObservedKeyPathKey];

    return (bindingInfo != nil)
        && (observedObject == destination)
        && [keyPath isEqualToString:observedKeyPath];
}

// in the tests specifying the view controller's behavior...

- (void)testAddButtonEnabledStateIsBoundToArrayControllerCanAdd {
    STAssertTrue([self checkObject:viewController.addButton
                        hasBinding:NSEnabledBinding
                          toObject:viewController.arrayController
                           through:@"canAdd"],
        @"The Add button's enabled state should be bound to the array controller's 'canAdd' property.");
}

Much clearer!

Tagged , , , , , , , , , ,

Objective-C 2.0 properties and to-many relationships

I’ve occasionally been asked about the appropriate form for properties representing to-many relationships in Objective-C 2.0.

Let’s start with the example of a recipe and its ingredients, represented by instances of the Recipe and Ingredient classes.

@interface Recipe : NSObject {
@private
    NSMutableSet *_ingredients;
}

@property (copy) NSSet *ingredients;

@end

This is a pretty straightforward interface for the Recipe class, but how should we actually implement it? You might first think of writing something like this:

@implementation Recipe

- (id)init {
    if (self = [super init]) {
        _ingredients = [[NSMutableSet alloc] init];
    }
    return self;
}

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

@synthesize ingredients = _ingredients;

@end

However, this will not do what you expect. In particular, whenever you manipulate the ingredients property, it always replace the value of the _ingredients instance variable used for its storage with a new, immutable NSSet!

What’s wrong with this? For one thing, you won’t be able to make any finer-grained changes to the ingredients property, so your code may wind up doing a lot of work unnecessarily. You’ll only ever post Key-Value Observing changes for the entire property, as well, not for individual manipulations; anything observing those changes will probably wind up doing extra work, too.

Why not instead change the type of the property itself to NSMutableSet * then? That way, your code could just manipulate the ingredients of a recipe directly, right? You could do that, but then you wouldn’t get any Key-Value Observing notifications for changes to the property. Why not? Because KVO is all about notification of property changes, and changing the object that stores a property’s data isn’t the same thing as changing the property itself.

What should you do then? Here’s how I would implement the Recipe.ingredients property instead of using the above @synthesize directive:

@implementation Recipe (IngredientsProperty)

- (void)setIngredients:(NSSet *)value {
    [_ingredients setSet:value];
}

- (NSSet *)ingredients {
    return [NSSet setWithSet:_ingredients];
}

@end

What’s different here is that I’m taking advantage of the fact that the instance variable backing the property is mutable. For just a getter and a setter, that isn’t a big deal. However, since I’m dealing with a to-many relationship, I wouldn’t just write a getter and a setter. I’d also write some of the additional relationship-KVC methods for the property, so I can manipulate the property more efficiently, and get finer-grained KVO notifications:

@interface Recipe (IngredientsProperty)

- (void)addIngredientsObject:(Ingredient *)ingredient;
- (void)removeIngredientsObject:(Ingredient *)ingredient;

- (void)addIngredients:(NSSet *)ingredients;
- (void)removeIngredients:(NSet *)ingredients;

@end

@implementation Recipe (IngredientsProperty)

- (void)addIngredientsObject:(Ingredient *)ingredient {
    [_ingredients addObject:ingredient];
}

- (void)removeIngredientsObject:(Ingredient *)ingredient {
    [_ingredients removeObject:ingredient];
}

- (void)addIngredients:(NSSet *)ingredients {
    [_ingredients unionSet:ingredients];
}

- (void)removeIngredients:(NSSet *)ingredients {
    [_ingredients minusSet:ingredients];
}

@end

By doing this, when I need to manipulate a Recipe’s ingredients property I can use -mutableSetValueForKey: to do so and any changes I make will be efficient. For example, if I’m creating a Recipe to represent Meghan’s Butternut Squash Panang Curry, I might write some code like this:

NSMutableSet *ingredients = [panangCurryRecipe mutableSetValueForKey:@"ingredients"];

[ingredients addObject:[Ingredient ingredientWithName:@"Butternut Squash" quantity:1]];
[ingredients addObject:[Ingredient ingredientWithName:@"Panang Curry Paste" quantity:1]];
[ingredients addObject:[Ingredient ingredientWithName:@"Coconut Milk" quantity:1]];

Instead of making several copies of the set as I make changes, the underlying mutable set is changed in as efficient a way as possible given the accessors I’ve implemented. I don’t have to do any extra work to make that happen.

I also get efficient KVO change notifications for the property, so if I have any user interface bound to it — whether through Cocoa bindings or, if I’m using Cocoa Touch, a “bindings lite” implemented atop KVO — the change notifications it receives will reflect exactly the changes made, instead of wholesale replacement of the set.

I could still improve the code above. I’m using -[NSObject(NSKeyValueCoding) mutableSetValueForKey:] to manipulate the Recipe.ingredients property. That means I don’t get nice Code Sense completion from Xcode, and have to remember the property’s name and spell it correctly when I use it in a string. So I’ll add the following property declaration and implementation:

@interface Recipe (IngredientsProperty)
@property (readonly, copy) NSMutableSet *mutableIngredients;
@end

@implementation Recipe (IngredientsProperty)

- (NSMutableSet *)mutableIngredients {
    return [self mutableSetValueForKey:@"ingredients"];
}

@end

You’re probably thinking something like “Wait a minute, readonly and NSMutableSet?!” That’s exactly what I mean to say, though: You can mutate the collection you get back (“read”) from the property, but not the property itself.

Update: On Twitter, a couple of people asked why I didn’t just use -[Recipe addIngredientsObject:] directly, since I have that available. I certainly could have done that, and it’d have all of the advantages I cite, and it wouldn’t require the creation of the proxy mutable set either. However, if I wanted to something more complex than just an addition, using the proxy mutable set is a significant advantage.

This is because the proxy mutable set (or array, if you’re using an ordered relationship and -mutableArrayValueForKey:) will do the heavy lifting of figuring out the right combination of the accessors your implemented accessors to perform an operation most efficiently. Also, technologies like Cocoa bindings will always use the proxy.

With this additional property in place, the entire Recipe class will look something like this:

@interface Recipe : NSObject {
@private
    NSMutableSet *_ingredients;
}

@property (copy) NSSet *ingredients;
@property (readonly, copy) NSMutableSet *mutableIngredients;

- (void)addIngredientsObject:(Ingredient *)ingredient;
- (void)removeIngredientsObject:(Ingredient *)ingredient;

- (void)addIngredients:(NSSet *)ingredients;
- (void)removeIngredients:(NSet *)ingredients;

@end

@implementation Recipe

- (id)init {
    if (self = [super init]) {
        _ingredients = [[NSMutableSet alloc] init];
    }
    return self;
}

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

- (void)setIngredients:(NSSet *)value {
    [_ingredients setSet:value];
}

- (NSSet *)ingredients {
    return [NSSet setWithSet:_ingredients];
}

- (NSMutableSet *)mutableIngredients {
    return [self mutableSetValueForKey:@"ingredients"];
}

- (void)addIngredientsObject:(Ingredient *)ingredient {
    [_ingredients addObject:ingredient];
}

- (void)removeIngredientsObject:(Ingredient *)ingredient {
    [_ingredients removeObject:ingredient];
}

- (void)addIngredients:(NSSet *)ingredients {
    [_ingredients unionSet:ingredients];
}

- (void)removeIngredients:(NSSet *)ingredients {
    [_ingredients minusSet:ingredients];
}

@end

And the code for creating the curry recipe becomes this, for which Xcode will give helpful Code Sense completion suggestions:

NSMutableSet *ingredients = panangCurryRecipe.mutableIngredients;

[ingredients addObject:[Ingredient ingredientWithName:@"Butternut Squash" quantity:1]];
[ingredients addObject:[Ingredient ingredientWithName:@"Panang Curry Paste" quantity:1]];
[ingredients addObject:[Ingredient ingredientWithName:@"Coconut Milk" quantity:1]];

As well, it continues to avoid making copies of the underlying collection representing the relationship, and it also continues to post fine-grained KVO change notifications rather than whole-property notifications, ensuring bound controls are updated efficiently.

So when you’re creating properties for to-many relationships whether they’re unordered (NSSet) or ordered (NSArray), consider using this approach to implementing them. It’ll take a little more code, but it’ll be a lot more efficient and more correct.

Bonus Round: Core Data

What about Core Data? Now that iPhone OS 3.0 has Core Data, in addition to Mac OS X, there’s really no excuse not to use it. But would you do anything differently above?

Of course. But since we’re talking about Core Data, it turns out that what you do different is actually write a whole lot less code. Here’s what the declaration of the Recipe class will look like if it corresponds to a Core Data entity:

@interface Recipe : NSManagedObject

@property (copy) NSSet *ingredients;
@property (readonly, copy) NSMutableSet *mutableIngredients;

@end

@interface Recipe (CoreDataGeneratedAccessors)

- (void)addIngredientsObject:(Ingredient *)ingredient;
- (void)removeIngredientsObject:(Ingredient *)ingredient;

- (void)addIngredients:(NSSet *)ingredients;
- (void)removeIngredients:(NSet *)ingredients;

@end

Notice that I’ve gotten rid of the instance variables section entirely. This is because Core Data manages the storage for your modeled attributes and relationships for you; you don’t need (and really don’t want) instance variables for them.

You’ll also notice that I put the additional to-many relationship accessor methods in their own category. To see why, take a look at the implementation of the class:

@implementation Recipe

@dynamic ingredients;

- (NSMutableSet *)mutableIngredients {
    return [self mutableSetValueForKey:@"ingredients"];
}

@end

Notice anything missing? All of the methods related to the modeled ingredients property! Core Data will not only generate an efficient setter and getter for the ingredients property automatically at run time, but will also generate implementations for the other ingredients to-many relationship accessor methods as well!

Core Data will generate the methods (at the latest) when you try to use them; it’s not dependent on having the category declaration available. That’s just for the compiler and IDE’s benefit when you’re writing code that uses those methods, so they can be completed by Code Sense and the compiler knows not to generate unknown-method warnings.

Changes

I added a bit after the first use of -mutableSetValueForKey: to address why one might want to use the mutable set proxy rather than just using the finer-grained KVC accessor methods directly.

Tagged , , , , ,

Singletons in Cocoa/Objective-C

I’ll preface this post with the standard advice: Don’t create singletons if you don’t absolutely have to. In general, if you’re creating a global “manager” object of some sort, you’re doing something wrong.

That said, there’s still occasionally a reason to have such a global singleton, such as a “default something.” The sample code in the Cocoa Fundamentals Guide goes to a lot more trouble than it needs to in order to ensure that a class is a singleton.

This is almost never what you want.

First off, you probably want your class to be testable in a variety of configurations. In your unit tests, instead of getting your shared singleton instance in your -setUp method and “resetting” its state in -tearDown, you’d be better off just instantiating a new instance in -setUp and releasing it in -tearDown.

Also, the example in the Cocoa Fundamentals Guide does a lot of work that it simply doesn’t need to. This is all you really need to do to create a singleton in Cocoa:

@interface SomeManager : NSObject
+ (id)sharedManager;
@end

@implementation SomeManager

+ (id)sharedManager {
    static id sharedManager = nil;

    if (sharedManager == nil) {
        sharedManager = [[self alloc] init];
    }

    return sharedManager;
}

@end

That’s it! The astute reader will notice, of course, that this isn’t thread-safe. I got rid of the @synchronized (self) because it won’t do the right thing; depending on what actual class is sent +sharedManager, the value of self will be different!

For the sake of argument, though, let’s say that you do want a singleton with which you can interact from multiple threads at once. One way to do this would be to create your singleton instance in +initialize since it will always be run, on a single thread, before any other methods in your class:

@implementation SomeManager

static id sharedManager = nil;

+ (void)initialize {
    if (self == [SomeManager class]) {
        sharedManager = [[self alloc] init];
    }
}

+ (id)sharedManager {
    return sharedManager;
}

@end

By doing this, you avoid the performance bottleneck of @synchronized taking a recursive lock every time +sharedManager is invoked.

If you want to get fancier, and it’s OK to temporarily have more than one instance of your singleton created, you could even use objc_atomicCompareAndSwapGlobalBarrier to assign the value to return from +sharedManager, though this is probably also more work than it’s worth; after all, +initialize will only be invoked once for your class. (Though it can be re-invoked as a side-effect of initializing subclasses, hence the if (self == [SomeManager class]) { } idiom.)

In all of the above cases, you’ve done a whole lot less work than the example in the Cocoa Fundamentals Guide, and your code is a lot more likely to be correct as a result.

Tagged , , ,

When to use properties & dot notation

I listened to a recent episode of the cocoaFusion: podcast about properties and dot notation today. There were a few interesting points brought up, but I felt a couple of the most important reasons to use @property declarations and dot notation weren’t addressed.

The biggest reason I see to use a different notation for both property declaration and property access than for method declaration and sending messages — even if property access ultimately results in a message send, as it does in Objective-C 2.0 — is separation of state and behavior.

In the ur-OOP days of Smalltalk, state was supposed to be encapsulated within objects entirely. This has become Smalltalk dogma and some developers have tried to propagate it to Objective-C: The idea that objects should never expose their state to each other, but instead only vend behaviors. It makes a certain amount of sense if you see objects purely as actors.

However, in today’s modern world we understand that objects aren’t just actors. Objects both “do things” and “represent things;” they’re nouns. And they have both internal state that they use in managing their behavior and external state they expose to the world.

You can use the same mechanism to do both, as Smalltalk does and as Objective-C did before 2007. However, it turns out that it can make a lot more sense to use different syntax to represent the distinct concepts, even if they’re handled by the same underlying mechanism.

For example, I might have a Person class and an NSViewController subclass that presents a Person instance in a view. The API to my Person class might look like this:

@interface Person : NSObject
@property (copy) NSString *name;
@property (copy) NSImage *picture;
@end

This sends a strong signal to the users of the class that name and picture are external state for a Person instance, leading me to write code like this:

Person *person = [[Person alloc] init];
person.name = @"Chris";
person.picture = pictureOfChris;

The intent of this code is clear: I’m not asking person to do anything, I’m just manipulating its external state. That may cause it to do things as a side-effect, but at least in the code snippet I’m looking at, I’m just interested in changing some state.

Now let’s see what the NSViewController might look like:

@interface PersonViewController : NSViewController
@property (retain) Person *person;
- (BOOL)updatePicture;
@end

And let’s see how I’d use one, assuming it’s been instantiated and wired up in my view hierarchy already:

selectedPersonViewController.person = person;

if ([selectedPersonViewController updatePicture]) {
    // note elsewhere that the person's picture is updated
}

Even though the -updatePicture method has no arguments and returns a BOOL I (1) don’t make it a property and (2) don’t use dot notation to invoke it. Why not, since it fits the form of a property? Because it doesn’t fit the intent of a property. I’m actually telling the view controller to perform some action, not just changing some state, and I want the intent of that to be clear to a reader of the above code.

That brings me to the other major reason to both declare properties using @property and use dot notation to access them: Xcode. The code completion technology in Xcode tries hard to provide you with a good default completion and good choices in the completion list. But this can be very difficult, especially with the combination of Objective-C’s dynamic dispatch and the sheer size of the frameworks: There are hundreds (!) of methods declared in categories on NSObject as a result of categories describing informal protocols, and any of those methods could be valid on an arbitrary instance.

Dot notation, on the other hand, is not valid on arbitrary objects. Even though it compiles to exactly the same sort of objc_msgSend dynamic dispatch that bracket notation does, from a type system perspective it actually requires a declaration of the property being accessed to work correctly. The reason for this is that the name of a property is not necessarily the name of the message selector to use in dispatch; think of a property hidden whose underlying getter method is named -isHidden.

This means that tools like Xcode can provide a much more streamlined experience for properties using dot notation. If I write the above code in Xcode, rather than MarsEdit, Xcode will not offer completions like -autorelease and -retainCount when I type person. — it will only offer me the properties it knows are on Person.

Now, you can invoke arbitrary getters or setters (so long as they have a corresponding getter) using dot notation. The compiler doesn’t require an @property declaration for the use of dot notation, just a declaration. I could have declared the Person.name property like this:

@interface Person : NSObject
- (NSString *)name;
- (void)setName:(NSString *)value;
@end

The compiler will compile person.name = @"Chris"; just fine with this declaration, to an invocation of -[Person setName:] — but Xcode won’t offer you code completion for it if you don’t use @property to declare it. By not offering to complete non-@property properties for dot notation, Xcode avoids offering you bad completions like autorelease and retain that are technically allowed but are abominable style.

Of course, one complication is that many frameworks on Mac OS X predate @property declarations and thus don’t expose their state this way. That means Xcode won’t offer you completions for their state with dot notation until those frameworks do. Fortunately for iPhone developers, UIKit uses @property declarations pervasively. You should too.

To sum up:

  • Use @property to declare the state exposed by your objects.
  • Use dot notation to get and set objects’ state.
  • Use method declarations to declare the behavior exposed by your objects.
  • Use bracket notation to invoke objects’ behavior.

This results in intention-revealing code that clearly separates state and behavior both in declaration and use.

Tagged , , , , , ,