Archive for the 'Programming' Category

An introduction to Cocoa and Cocoa Touch

Wednesday, February 3rd, 2010

If you know someone who’s recently taken up programming the Mac or the iPhone (or both), please give them one (or both) of these links:

As a frequent answerer of questions on Stack Overflow, I see certain patterns—not just frequently-asked questions, but also frequently-unasked questions: Things that are biting the questioner that they don’t know about.

Sometimes they’re thinking about things the wrong way (e.g., using property list objects where they should have a model). Sometimes there is a route to a solution (“my app is slow” “run Instruments”), but they don’t know about that route. Often, they’ll use wrong terms that are right on another platform (like “member variable”), like a speaker using their native language’s pronunciation rules when speaking a foreign one.

To help people over these speed bumps, I’ve composed an introduction for new Cocoa and Cocoa Touch programmers. (Both of the above links redirect to it.)

If any part of it doesn’t help them (i.e., is unclear or wrong), I’d appreciate it if you’d let me know, either here or by email.

Reunification

Tuesday, February 2nd, 2010

A common question from people new to Objective-C is “why do I have to separately alloc and init? Why can’t I just call one thing and get a fully initialized object?”.

It’s certainly not how other environments do it. Usually, you call one function or class method, and you get an object. Cocoa makes you send two messages: one to the class, then another to the fresh, uninitialized instance you got back. What does Cocoa know that those other environments don’t?

There are two reasons why alloc and init are separate:

  • “NSResponder”* says that sometimes, NeXT wanted to initialize the same object multiple times.

    This is interesting, but horrifying to modern readers. Practically all init methods I’ve seen do not handle the case of initializing the already-initialized; they blindly assign newly created/retained objects to the ivars without checking for existing objects there.

    A bigger problem is when the init method releases the receiver and returns some other object; in the second message, the “other” object may in fact be the receiver (returned from the first message), so [self release] this time would be killing off an object that should stay alive. On the other hand, retaining the object before re-initializing it will create a leak if the object doesn’t release itself. Unpredictable behavior is bad.

  • On the same Stack Overflow question, Darren points out that alloc is shorthand for allocWithZone:; if allocation and initialization were merged in Cocoa, then, to maintain the same functionality, every initializer would need to take a zone parameter, and optionally come in a flavor without one. You can imagine how a proliferation of initializers would ensue.

    This is essentially what the documentation says: “Separating allocation from initialization gives you individual control over each step so that each can be modified independently of the other.” I.e., both steps can be customized, so they must remain separate so that you can customize either or both.

So, there are two practical reasons why Cocoa’s designers separated allocation from initialization.

But let’s revisit this with modern eyes:

  • As I mentioned, in modern Cocoa, initializing an instance again is risky at best. In practice, I don’t think anybody does it, and if anybody does, they probably feel guilty about it and mean to refactor that code “someday”.
  • Nobody uses zones anymore.

That blows those two reasons away.

So, let’s imagine what life would be like if they had never existed in the first place, and allocation and initialization had remained one task:

+ (id) newWithFramistan:(Framistan *)framistan {
    id obj = [super new];
    if (obj) {
        obj->framistan = framistan;
    }
    return obj;
}

Right away, you can see several advantages:

  • We can name our local variable “framistan”, not “newFramistan” or anything like that.
  • No more assignment in condition (if ((self = …))).
  • No more assignment to self (which should make Wil Shipley happy).
  • Eliminates the problem of [super init] returning a different object, whereupon you would have to release the receiver. Since the receiver is the class, there is nothing for the upstream-initialized object to be different from. If the superclass wants to return an existing object, it can just do that.
  • Related to the first point, we no longer have a name conflict between instance variables and local (especially argument) variables. In init methods, we resolve this conflict with style rules, such as the aforementioned newFramistan for locals or m_framistan for instance variables; in this newWithFramistan: method, the conflict doesn’t exist in the first place.
  • There is never an uninitialized object that the caller could leave lying around. We’ve all seen (or written) code like Foo *foo = [Foo alloc]; [foo init];; in this alternate universe, such faux pas are impossible.

There are trade-offs:

  • It’s one line longer. (Depending on your employers’ level of cluefulness, this may be a small advantage.)
  • Since you’re not in an instance, you have to prefix every instance-variable access with obj->. I can see how this could get tedious; on the other hand, this is what prevents ivar-vs.-local name conflicts.
  • If you use object controllers that automatically prepare their content, they’ll use alloc and init, bypassing this initializer. I’ve never used the automatic-content-preparation feature, so this doesn’t affect me.
  • It’ll be less than familiar to anybody who hasn’t read this post, and it’s certainly a change from currently-typical Cocoa code.
  • Doing this in a subclass of a class that has an unusual designated initializer, such as NSView with its initWithFrame:, could get tricky.

My opinion is mixed. On the one hand, real problems with the init way of doing things are rare for anyone who knows the ropes. On the other hand, it sure is more straightforward, isn’t it?

What do you think?

* Presumably the same one most of us recognize as John C. Randolph, although there’s no direct evidence of this on his SO profile.

Blog posts vs. web pages

Monday, January 25th, 2010

Steve Smith says “Stop Blogging”:

I mean it. All of you people are writing fantastic, useful articles about code, methods, and technologies, but you’re putting them in blog posts — a date-based format that encourages us to leave things as they were, historically.

This got me to thinking about the difference between two of the tutorials I’ve published.

The pointers tutorial is a single web page. There’s a date stamp, but it’s way down at the bottom. The ASL series is nine blog posts.

In the three years since the previous version of the pointers tutorial, dozens of people emailed me to tell me about its major errors.

In the two years since I published the last of the ASL series (ignoring approximately a week afterward), nobody has told me of an inaccuracy in any of the posts.

There are a number of possible explanations for the ASL series receiving fewer (that is, no) corrections:

  • That its audience is narrower: Anyone who programs C has to deal with pointers. Only a very few Mac OS X programmers will ever touch ASL.
  • That it is less visible: One of these is linked from my home page and plenty of CS course reading lists (exhibits A, B, C, and D), and was linked for a while from the Wikipedia article on the C programming language; the other is practically unknown to anyone who wasn’t subscribed to my blog at the time.
  • That I’m just that good. (Ha!)
  • That ASL hasn’t changed at all since Leopard. (Ha!)

Smith writes from the perspective of the author and publisher, who must maintain a web page; he says that the author and publisher finds no (or not much of) such obligation for a blog post. I think the difference in my supply of corrections hints at a reader side to this, although, as shown above, my two examples are hardly comparable.

I have been meaning to move the ASL tutorial into a pointers-style web page at some point, although I don’t know when. I may start receiving corrections then, which means I’ll have to spend time to fix them. The flip side to that is that if I leave it as blog posts, I’ll have that time for other things, but the posts will be consigned to periodically-increasing inaccuracy.

I expect to think more about Smith’s suggestion.

There’s also the merit of the word “blog”, which is wearing thin for me.

The trilogy is now complete

Saturday, January 23rd, 2010

The third video of last month’s meeting is now up. Here are three easy-to-remember links:

  1. http://bit.ly/CHLF2009Leaks1
  2. http://bit.ly/CHLF2009Leaks2
  3. http://bit.ly/CHLF2009WebInsp

You’ll notice that the third video is not CHLF2009Leaks3.

Unlike the other two, this one features Scott Ellsworth, our organizer, demonstrating the Web Inspector in WebKit. He starts off in Safari, then switches over to Chrome. He also talks about a profiling tool that’s part of Google Web Toolkit called Speed Tracer, although he wasn’t able to finish a demo of it in time for the meeting, so he talks about one of the examples instead.

I don’t think I’ll link these here anymore. If you want to find out about future CocoaHeads Lake Forest videos, subscribe to the CocoaHeads Lake Forest channel on Vimeo.

CocoaHeads Lake Forest videos

Monday, January 18th, 2010

It’s been in editing for over a month, but now, it’s finally done. I’ve just uploaded the second part of last month’s meeting of CocoaHeads Lake Forest. There’s one more to go from last month, and then I can start posting the video from this month.

This one’s a lot more random than the first one. Portions of my own presentation are only part of what you’ll see in this video.

More long-term, I’ve created a channel on Vimeo for all past and future CocoaHeads LF videos.

The myth of Carbon’s 64-bit unavailability

Monday, January 18th, 2010

There’s a recurring myth going around, which goes something like this:

In fact, using Carbon locks you out of 64 bit.

No, it doesn’t.

The truth is that some APIs that are part of the Carbon sub-frameworks are not available in 64-bit. Merely linking against Carbon does not mean your app suddenly stops working in the 64-bit world.

Carbon itself is just an umbrella framework. It doesn’t have any APIs that it provides immediately; everything comes from either another framework or one of its sub-frameworks.

Examples of the first category include Core Foundation, Core Services (home of Launch Services), and Application Services (home of Core Graphics). Even these are not immune to the myth, as demonstrated by the comment I linked to above: It’s on an answer suggesting a Core Foundation function. The answerer referred to it as a “Carbon function” (true in a sense), and the commenter pounced.

Many things that were once explicitly considered part of Carbon, such as the File Manager and Resource Manager, are now part of Core Services. Note that they haven’t even been consigned to the Legacy Library!

In the other category, even some APIs that remain strongly identified with Carbon, by being in a direct sub-framework of Carbon, are still at least partially around. One of these is the Carbon Event Manager, which even has the word Carbon in its name. Try registering a hot-key with it in a 64-bit-only app—it’ll work. (That one is in the Legacy Library. I should probably file a bug on that.)

What is deprecated and not available in 64-bit, as you can see in the Carbon Event Manager Reference, is anything that you would need to build your application on Carbon. That’s what’s deprecated: the concept of a Carbon application. Only Cocoa apps remain.

But some parts of “Carbon” are useful for things other than building a Carbon application. You can use them from a Cocoa application, or from a command-line tool.

Those APIs are still around. They are not deprecated, they are still useful, and they are still available in 64-bit. Use them freely.

(Oh, and before anybody mentions it: No, those NSEvent class methods introduced in Snow Leopard are not direct replacements for Carbon Event Manager hot-keys. You’d have to sift through the events yourself, whereas Carbon Event Manager filters them for you and only calls your function when your key is pressed. The correct analogue would be CGEventTap.)

Pointers tutorial 1.3

Saturday, January 16th, 2010

At long last, a new version of Everything you need to know about pointers.

The most significant changes are long-overdue corrections regarding declarations of const pointers and the difference between arrays and pointers. You can—and, if you learned how to work with pointers from this tutorial, should—read all of the changes in the delta between 1.2 and 1.3.

Ship-It Saturday: IconGrabber 2.0.1

Sunday, January 3rd, 2010

The last time I released a version of IconGrabber was only a week after Valve released Half-Life 2—way back in 2004. That game wasn’t even on my radar then, since I couldn’t run it on my PowerPC-based Mac!

Just over five years later, I’ve played all of the Half-Life 2 games and love them, and IconGrabber returns with some bug fixes and support for the new bigger icon sizes introduced in Tiger and Leopard. Version 2.0.1 is available from the IconGrabber home page.

Ship-It Saturday: Translate Text

Sunday, December 27th, 2009

Real artists ship.

Steve Jobs

With the idea that an application that’s 95% finished and in active use is better than an application waiting for 100% in the seclusion of my hard drive, Ship-It Saturday is where I dust off a program that I have 95% finished, call it done, and just ship it already. I hope to make this a regular feature, although I have no idea how frequently I’ll do it.

Today’s winner is Translate Text, an app I wrote to make handling Adium feedback emails easier. Just select some text, then choose the service corresponding to the language it’s in (or the auto-detect-language-and-then-translate service). A window will open with the original, a couple of language pop-up menus, and the translation.

Screenshot of myself invoking the French-to-English service through a contextual menu.

More information, both screenshots, and the downloads at the Translate Text web page.

Warnings I turn on, and why

Saturday, November 7th, 2009

I’ve started turning on most of Xcode’s warning options and one warning-related build setting in all of my personal projects. I suggest you do the same.

ADDED 2013-09-27: The easiest way to do this nowadays is to use this xcconfig file, which turns all of the settings described here on at once.

There are some warnings I don’t turn on, for any of several reasons:

  • They’re inapplicable. For example, “‘Effective C++’ Violations” doesn’t apply to me, because I don’t write C++ code.
  • They don’t help anything. An example is “Four Character Literals”, which is about 'abcd' literals for four-byte-code types such as OSType. These sacrifice something convenient for no benefit, so I leave them off.
  • They are impossible for me to fix. An example is “Multiple Definition Types for Selector”. Cocoa raises that one all over its headers, and I can’t do anything about Cocoa.

The rest of the warnings, I turn on because either they make something clearer or they tell me about either real or potential (i.e., future real) bugs. They are:

  • Check Switch Statements

    Warn whenever a switch statement has an index of enumeral type and lacks a case for one or more of the named codes of that enumeration. The presence of a default label prevents this warning.

    Leave no case unhandled.

    Consider whether a default: label is appropriate for your enumeration. If your switch statement handles all possible values, cut out the default and assert that the value is one of the possible ones instead. An easy way to do this, if the enumeration values are serial and the enumeration is not part of an API you expose, is to have one extra name defined as the number of possible values:

    enum Foo {
    	kFooFoo,
    	kFooBar,
    	kFooBaz,
    	kFooNumberOfValidFooValues
    };
    

    Then, in your assertion macro, compare the value against that name:

    #define MyParameterAssertValidFoo(foo) \
    	NSAssert1((foo) < kFooNumberOfValidFooValues, @"Invalid Foo value: %d", (foo));

    When you add kFooQux, insert it above kFooNumberOfValidFooValues, and the value of kFooNumberOfValidFooValues will increase by one to fit it.

    The result is that your switch statement covers all known values for the enumeration (or you get a warning because it doesn't), and your method throws an exception (from the assertion) whenever anyone passes an unknown value.

  • Hidden Local Variables

    Warn whenever a local variable shadows another local variable, parameter or global variable or whenever a built-in function is shadowed.

    One common way to get this warning is to name a variable index, because there is a function by that name in the standard C library. That's not as much of a false positive as you may think: If you fail to declare your index variable, all your references to it will actually refer to the index function. You can see how it would be bad to send a message such as [myArray objectAtIndex:index] with this bug.

    The solution is simple: Never, ever name a variable index.

  • Implicit Conversion to 32 Bit Type

    Warn if a value is implicitly converted from a 64 bit type to a 32 bit type.

    This is most useful when converting old code to work correctly in a 64-bit architecture. Storing a pointer into an int variable (such as a reference constant) when targeting an LP64 architecture is a good way to get this warning, and rightly so.

  • Initializer Not Fully Bracketed

    Example, Here initializer for a is not fully bracketed, but that for b is fully bracketed.

    	int a[2][2] = { 0, 1, 2, 3 };
    	int b[2][2] = { { 0, 1 }, { 2, 3 } };

    This is a cleanliness warning. It also applies to structures, such as NSRect:

    NSRect warns = { 0.0f, 0.0f, 640.0f, 480.0f };
    NSRect doesNotWarn = { { 0.0f, 0.0f }, { 640.0f, 480.0f } };

    (In real code, I'm more likely to use NSZeroPoint instead of the { 0.0f, 0.0f } element above. It's harder to spell that wrong and get away with it than it is to get away with typing 9.9f, 1.1f, or 2.2f instead of 0.0f.)

  • Mismatched Return Type

    Causes warnings to be emitted when a function with a defined return type (not void) contains a return statement without a return-value. Also emits a warning when a function is defined without specifying a return type.

  • Missing Braces and Parentheses

    Warn if parentheses are omitted in certain contexts, such as when there is an assignment in a context where a truth value is expected, or when operators are nested whose precedence people often get confused about.

    Also warn about constructions where there may be confusion to which if statement an else branch belongs. Here is an example of such a case:

    	if (a)
    		if (b)
    			foo ();
    	else
    		bar ();

    In C, every else branch belongs to the innermost possible if statement, which in this example is if (b). This is often not what the programmer expected, as illustrated in the above example by indentation the programmer chose.

    This may appear to be just a cleanliness warning, but as you can see from the example, it can also warn you about code that may not flow the way you expect it to.

  • Missing Fields in Structure Initializers

    Warn if a structure's initializer has some fields missing. For example, the following code would cause such a warning, because "x.h" is implicitly zero:

        struct s { int f, g, h; };
        struct s x = { 3, 4 };

    This option does not warn about designated initializers, so the following modification would not trigger a warning:

        struct s { int f, g, h; };
        struct s x = { .f = 3, .g = 4 };

    I'm not sure why it warns about the former and not the latter, since all the members get initialized in both code examples (C99 §6.7.8 ¶21). If nothing else, this warning is good motivation for you to switch to designated initializers, which make your code more explicit about which members it's initializing.

  • Missing Newline At End Of File

    Another cleanliness warning—this one, about the cleanliness of diffs.

  • Sign Comparison

    Warn when a comparison between signed and unsigned values could produce an incorrect result when the signed value is converted to unsigned.

  • Strict Selector Matching

    Warn if multiple methods with differing argument and/or return types are found for a given selector when attempting to send a message using this selector to a receiver of type "id" or "Class". When this setting is disabled, the compiler will omit such warnings if any differences found are confined to types which share the same size and alignment.

    I don't turn this one on, because it's unnecessary. When the multiple declarations differ significantly (e.g., one method returns an object and the other returns a float), the compiler will raise the warning whether it's turned on or not. When the declarations don't differ significantly (e.g., both methods return an object), the difference won't cause a problem, so you don't need to worry about it.

    So, you should leave this one off.

  • Typecheck Calls to printf/scanf

    Check calls to printf and scanf , etc, to make sure that the arguments supplied have types appropriate to the format string specified, and that the conversions specified in the format string make sense.

    The biggest reason to turn this on is that it checks your use of methods that take a nil-terminated list of arguments:

    NSArray *array = [NSArray arrayWithObjects:@"foo", @"bar"];

    That message should have a nil after the last argument. With this warning turned on, the compiler will point out that I don't.

    The ostensible main reason to turn this on is to have the compiler check your uses of printf and scanf formats. I don't use printf often (and I never use scanf), so that's not so important for me, but when I do, this could come in handy.

    Sadly, it doesn't work on NSLog calls. This has been fixed in Clang as of 2013. Your printf, NSLog, and stringWithFormat calls all get checked (despite the name of the setting not having changed).

  • Undeclared Selector

    Warn if a "@selector(...)" expression referring to an undeclared selector is found. A selector is considered undeclared if no method with that name has been declared before the "@selector(...)" expression, either explicitly in an @interface or @protocol declaration, or implicitly in an @implementation section.

    Another benefit of this warning is that you can use it to get a warning when you pass a wrong key to a KVC, KVO, KVV, or Bindings method. Uli Kusterer has a macro for that.

  • Unused Functions

    Warn whenever a static function is declared but not defined or a non-inline static function is unused.

    Works best with a policy of declaring any function as static that you don't need to be visible elsewhere in your program.

  • Unused Labels

  • Unused Values

  • Unused Variables

    These follow the general rule of “code you don't have is code you don't have to debug”. If you're not using a label, expression statement, or variable, you don't need it, and you will find your code clearer without it.

    You may notice that I don't turn on Unused Parameters. Most times when I trip that warning, it's a callback function or method, so I can't get rid of the argument. Rather than litter my code with bright yellow #pragma unused(foo) directives, I prefer to just turn this one off. (See my rule above about less code being better.)

Once I have turned on all of these warnings and then eradicated them from my code, I turn on two more build settings:

  • Treat Warnings as Errors

    I call this “hardass mode”.

    Remember what I said above: Almost all of these warnings represent real or potential (i.e., future) bugs in my program. Rather than tolerate them, I turn this setting on so that any time I write such a bug, I break the build.

    I haven't been able to turn this on yet in Adium or Growl, although I have turned it on in Adium's Spotlight-importer project. I do, however, turn it on in all of my solo projects.

  • Run Static Analyzer

    Activating this setting will cause Xcode to run the Clang static analysis tool on qualifying source files.

    The Clang Static Analyzer is the find-your-bugs-for-you tool you've heard so much about. This setting makes Xcode run it whenever you build. Thus, every build, you get all those warnings errors and your analysis results.

    Whenever possible, I leave this on; if there's a source file that it takes a long time to analyze (e.g., GrowlPluginController.m), then I turn it off, but only then.

UPDATE 2009-11-22: Jonathan “Wolf” Rentzsch wrote a script to turn on all of these settings in all of the projects you have open.

UPDATE 2009-11-28: Updated the entry on “Typecheck Calls to printf/scanf” after seeing that Jeremy W. Sherman pointed out a much better benefit of it in a comment on a Stack Overflow answer.

UPDATE 2009-12-05: Corrected the discussion of the index problem. You can't use index, or any other function, as a C-array subscript, so the problem only affects higher-level arrays, such as NSArray.

UPDATE 2013-09-27: Added link to xcconfig; updated section on “Typecheck Calls to printf/scanf”.

The peril of index(3)

Thursday, November 5th, 2009

This is mainly for Andy Finnell on Twitter, who wonders why some of us avoid naming variables index.

I pointed out that there is a function in standard C named index, and this causes one of two problems: If you declare a variable named index, you have shadowed the function and should get a warning for that; if you fail to declare the variable, you pass the pointer to the index function as your array index, which is probably not what you intended.

I say “should” there because, as he noted in his response, the shadowed-name warning is off by default. You should turn it on, because it catches bugs. In fact, the index bug is one that it can prevent.

Suppose you do name a variable index, and either you don’t have the shadowed-name warning turned on or you ignore it. You initialize the variable with an index, but don’t otherwise assign to it. Then, you attempt to access an object in an array by this index.

All well and good so far. index is a variable, so everything works as intended.

But then, one of several things happens:

  1. You comment out both the declaration and the usage of index, for whatever reason, but then you uncomment the usage but forget to uncomment the declaration.
  2. You update and/or merge in your version-control system, or otherwise apply one or more diffs. Usually, this works, but today isn’t your lucky day: The merge breaks your source code. Perhaps it introduces conflicts, and you resolve them incorrectly. Or maybe it breaks the code silently (e.g., by merging in another branch’s division of this function into two).
  3. You move the code to another location, but you forget to move half of it, or you move one half and delete another, forgetting that the declaration of index was in the code you deleted.

You had a variable named index, but now you don’t—but the index function is always there*. Since there is something named index, your code compiles. It’s the wrong type, so you’ll get a warning, but maybe you don’t notice it.

Then you run the code and it crashes. Why? Because you passed a function as the index into an array.

In the worst possible case, it was #2 and you weren’t aware that this code was affected. Maybe you’d been working on something else. Anyway, since you hadn’t been working on the now-broken code, you aren’t testing it**, so you don’t know that it’s now broken.

So you ship it. You ship this index-way-out-of-range crasher. And then your user runs the code and gets the crash.

This isn’t theoretical. I’ve had this happen more than once (fortunately, not in the hands of a user). It’s one reason why I turn on the shadowed-name warning and “Treat Warnings as Errors”, and it’s the reason why I never use index as a variable name.

UPDATE 2009-12-05: To clarify, this problem does not affect C arrays, as C does not allow you to use a pointer in an array subscript. It mainly affects higher-level array interfaces, such as Cocoa’s NSArray.

* Assuming that, directly or indirectly, you’ve included string.h. If you’re using Cocoa, you have (Core Foundation includes it).

** Unless, of course, you have automated test cases covering this code, and you run those.

How not to use UTIs

Tuesday, September 22nd, 2009

John C. Welch has written an article telling you to use UTIs to replace creator codes.

It is wrong.

Daring Fireball, rosscarter.com, and (the most sober of the bunch), TidBITS have all gotten on the “Apple has abandoned creator codes, now we’re screwed, damn you Apple” bandwagon. They’re all right about one thing: Apple has dumped creator codes in Snow.

So before you panic, there’s a replacement mechanism, the UTI, or Universal Type Identifier.

No. Uniform Type Identifiers are a replacement for type codes (and MIME media types, and filename extensions), not for creator codes. There is no replacement for creator codes.

Uniform Type Identifiers are just that: They identify types of data. Using them for anything else is misusing them.

Ideally, Coda should assign an application-specific UTI for CSS files it creates.

No, it should not.

As it turns out, Coda is a UTI-aware application, and according to Coda’s info.plist file, that identifier is com.panic.coda.css.

And that identifier is wrong, because CSS is not Panic’s format.

I use CSSEdit. Currently, it doesn’t declare a UTI, but if they should follow Coda’s example, they should make one up of their own, such as com.macrabbit.cssedit.css. Now we have one type with two names. Which is right?

Suppose I write an application that accepts CSS data. Which UTI do I look for: com.panic.coda.css or com.macrabbit.cssedit.css? Should I look for both of them? What if I find both? What if a third developer releases a CSS editor? Now I have to keep up with the entire population of Mac CSS editors just to accept all the many names for one type.

The right type identifier would be something like org.w3.css or org.w3.cascading-style-sheets, following the rule that the type should be named after whoever controls it. The W3C controls CSS, so its UTI should be named after them. Some other formats, such as PNG, aren’t controlled by anybody, so they go in public.

You might point out public.html and public.xml, as both of those are also controlled by the W3C. Obviously, I disagree that these should be in public.*. But it’s too late to change them now, so we have to put up with them.

Better examples include com.adobe.pdf and com.microsoft.word.doc. In each of these cases, some third party controls the format, so they get the format’s UTI named for them. Notice that Preview does not invent a com.apple.preview.pdf UTI, and TextEdit does not invent a com.apple.textedit.word.doc UTI; they use the UTIs named for the creators and maintainers of those types.

So now we see a problem. All the text-ish files have the same type identifier: com.apple.traditional-mac-plain-text.

Because they are all the same type. And that type is named after Apple because Apple controls that format (in this case, a text encoding).

The Photoshop PNG file is typed as public.png.

There’s no such thing as a “Photoshop PNG” file. PNG is an open format controlled by no-one (or, arguably, the W3C, in which case the type should have been named for them). What you have is a PNG file that you created in Photoshop. That latter detail is irrelevant to its type, which is why HFS had the creator code separate from the type code in the first place.

If there is such a thing as a “Photoshop PNG” file (that is, if Adobe incompatibly extends the PNG format in some way), then they should assign that format its own name (say, com.adobe.png), because it’s a different format.

If you take away the creator code, you’re screwed, because all you have are the extensions.

Exactly why John Gruber, Ross Carter, and Matt Neuberg don’t like the change.

Coda CSS file props:

displayed name:"test.css", 
creator type:"TStu", 
type identifier:"com.apple.traditional-mac-plain-text",

I’m surprised you didn’t notice this. Why isn’t this file’s type identifier com.panic.coda.css?

… why aren’t any of these applications doing the right things? Pages ’09 does. It sets the type for .pages files to “com.apple.iwork.pages.pages”.

Because it’s Apple’s own format specifically for Pages. Again, see also com.microsoft.word.doc.

Unsurprisingly, it doesn’t even have a creator code.

Yeah. Cocoa makes it difficult to apply a creator code to a file and doesn’t do it automatically, so expect most Cocoa apps to not do it.

Even thought the default for the .html extension is BBEdit, the UTI overrode that. When I changed the handler for public.html to BBEdit, then the file opened in BBEdit. That’s exactly the behavior I’d expect, and it matches what you got with Creator Codes.

It matches what you got when you assigned the default handler of a file type, as well. That’s what you did the newer equivalent of.

There never was a way to set which application opened files that had a given creator code. That was what the creator code was for: Determining which application would opened the file.

Yes, Apple did abruptly kill off Creator Codes, however, they’ve been warning about that for some time now.

Sort of. They’ve been warning that they’d kill off the combination of file type codes and creator codes. UTIs are the replacement for file type codes; as I said above, there is none for creator codes.

Now, I know that ‘simple’ is a big fat lie when it comes to application development, however, at some point during the 10.5 lifecycle, all these applications should have been updated to not only support UTIs, but to use them. Instead, they all relied overmuch on FIle Types/Creator Codes …

Actually, it was more common to use filename extensions. See what I said above about the difficulty of assigning file types and creator codes from a Cocoa app. I think that was actually quite rare, simply because filename extensions were so much easier.

… and now that those are gone, well, the OS does what it can with the information it has available.

No, it doesn’t. The creator code information is still available, and the OS ignores it. The OS now only uses type information to determine how to open a given file, except for files that the user has assigned a specific application to.

Oh, and what about when you change a file association in the Finder? Well, unsurprisingly, the Finder cheats. It adds a resource fork to the file with the path to the desired application coded within. … [M]aybe the Finder could start doing the right thing too?

Agreed. I say it should set the file’s creator code.

Incidentally, I tested in Tiger, Leopard, and Snow Leopard, and Finder did this resource trick in all three versions. If the Info window ever did set the file’s creator code, it hasn’t done that for many years.

If the only way to have a unique UTI associated to a file is for that file to use a completely unique file extension, then WHAT THE FUCK GOOD ARE UTIS? Fucking seriously, why the FUCK bother? BBEdit creates TEXT FILES. Does Apple seriously expect that Bare Bones, to properly use UTIs, is going to now create a .bbedittext extension, a .bbedithtml extension, a .bbeditohmyfuckinggodwhatthefuckisgoingon extension, then make you EXPORT to ‘standard’ extensions, just so you can know a file created in BBEdit will open in it?

And now you know why smashing type information and creator/opener information into a single value is a bad thing.

If this is what Apple is pushing, then everyone who signed off on non-settable UTIs is a fucking idiot…

There is no reason why the average user should be able to change the type of a file. If they created an HTML file, it’s an HTML file, and there’s no reason for a user to be able to set it to anything different unless they really know what they’re doing. (I’ve done it, and I’m assuming you have, too. We’re exceptions.)

What you want to do is to change which application opens the HTML file, and that is completely separate from the fact that the file contains HTML.

The other way to install the Mac Reference Library

Wednesday, September 2nd, 2009

Starting with Xcode 3.2, the Xcode installer package no longer includes a local copy of any developer documentation. Instead, you have to either go to the website (which is what the redesigned Documentation Viewer window does) or download the documentation within Xcode.

Both solutions have their own problems. Reading the docs on the website can be frustrating if you’re streaming or downloading something in the background. And downloading within Xcode is dubious if your internet connection is not super-fast or is flaky, because Xcode cannot resume downloads.

There is a third solution.

  1. In Xcode’s Preferences, click on an info button at the right edge of the list of docsets, or right-click on the docset and choose “Get Info”.
  2. Select the row labeled “Feed URL”, and copy it.
  3. In a text editor or text field, paste the text, then edit it (it’s the whole row, not just the value) down to the URL alone. There’s a period (full stop) at the end of the text; it’s not part of the URL, so make sure you delete that.
  4. Open the URL in a feed reader.
  5. On the most recent entry, copy the URL for the enclosure.
  6. Paste it into your download manager or browser Downloads window.

Assuming your download manager or browser supports resuming downloads, you now have a way to pause the download for any reason that may arise, and resume it from that point.

Of course, then you have to install what you downloaded. You’re probably not used to seeing xar files (although you’ve seen more than you think—flat packages are based on them), so you may not know what to do with them.

  1. Pop open a terminal. cd over to where you downloaded the xar archive.
  2. pushd /Developer/Documentation/DocSets
  3. sudo xar -xf ~+1/filename.xar
  4. Once that finishes, delete (or back up) the xar file.

Xcode’s Documentation Viewer window (or your browser) should suddenly be much quicker.

Git fetch weirdness explained

Sunday, August 30th, 2009

In another tussle with Git, I performed the following sequence of commands:

  1. cd mach_star-rentzsch
  2. git fetch (from GitHub)
  3. cd ../mach_star-boredzo
  4. git fetch rentzsch (in this context, my git-remote alias for ../mach_star-rentzsch)
  5. git merge rentzsch/master

Step 5 failed with “Already up-to-date”.

What? I just fetched! I should have new commits to merge in!

Nope. For one thing, this output from step 4:

From ../mach_star-rentzsch
 * [new branch]      master     -> rentzsch/master

seems to mean “OK, here’s a new name for the master branch of that other repository, but we didn’t actually bring in any commits”.

The reason it didn’t bring in any commits is because git fetch apparently only fetches commits that are ancestors of the source repository’s current HEAD. In English: git fetch cares what you have checked out in the source repository.

It’s because I had fetched in step 2, and thereby not changed my HEAD, that step 4 did not see anything new to fetch. I don’t know why it works that way, or why they consider it useful.

Anyway, the “correct” sequence of steps is not much different: git pull, not fetch, in step 2 above. Or use Mercurial, which I’ve found makes a lot more sense in general.

It’s entirely possible that I’ve figured this out the wrong way, so take this entire explanation with a grain of salt.

Variables for clarification

Friday, August 14th, 2009

Before:

if (![newTrackURL isEqualToString:trackURL] || ([newTrackURL hasPrefix:@"http://"] && !([lastPostedDescription isEqualToString:displayString]))) { // this is different from previous notification, or it's a stream and the playing track has changed

After:

BOOL URLChanged = ![trackURL isEqualToString:newTrackURL];
BOOL isStream = [newTrackURL hasPrefix:@"http://"];
BOOL descriptionChanged = ![lastPostedDescription isEqualToString:displayString];
if (URLChanged || (isStream && descriptionChanged)) {

Why remove the comment? Well, I had just changed the code to what you see in the Before example, but I had not changed the comment, and I thought I was ready to commit. I almost committed a stale comment. It’s that easy. Luckily, I caught it in reading the patch before I qfinished it, so I was able to change the comment to what you see above.

Now I have no comment at all, but the code is clear, so I don’t need one. This is an improvement.

Here, have a coupon

Sunday, July 26th, 2009

Voices That Matter: iPhone Developers Conference
October 17th and 18th.

This October 17th and 18th, there’s a conference for iPhone developers in Boston, which the organizers asked me to attend.

The conference is called Voices That Matter: iPhone Developers Conference, and the titular voices include Aaron Hillegass (famous for his book), Erica Sadun (famous and infamous for her jailbreak work and advocacy), Bill Dudney (famous for his book), Stephen Kochan (somewhat famous for his book), Jonathan “Wolf” Rentzsch, Fraser Speirs, and Daniel Jalkut.

As most of you know, I’m not an iPhone developer—I write for the Mac only. So I declined that part of the offer.

The other part was a coupon for you, my readers. I know many of you probably are iPhone developers, so I asked whether they would still like me to give you that coupon code. They agreed, so here it is:

PHBLOG

(Those of you who read Jesper’s weblog may recognize it.)

Without the coupon, the registration fee is $495 until September 12th, $695 thereafter. The Word document they sent me says that that the coupon will knock $100 off.

Enjoy the conference!

System vs. Target in PackageMaker

Saturday, July 25th, 2009

The PackageMaker user guide doesn’t explain the difference between “system” and “target” in PackageMaker’s pop-up of Requirement criteria:

For example, “System OS Version” versus “Target OS Version”.

So now that I’ve figured it out, I’ll fill in the gap for you.

  • System is the volume that the installing user is booted from.
  • Target is the volume that the Requirement is testing. (Your Requirements are applied for each volume.)

So if you want to make your Installer package installable to any bootable volume, make it installable to any volume and add a Requirement for Target OS Version. (Another method you may try is “File Exists on Target: /Library”.)

If, on the other hand, you want to make your Installer package installable to the Home folder, make it installable only to the Home folder and add a Requirement for System OS version.

How you can get this wrong

If you make your package installable to the Home folder but test the Target OS Version, your package is broken: It does not work for those of us who have our Home folder on a non-bootable volume (in my case, separate from two other, bootable volumes). You must use the System OS Version, and hope for the best.

If you make your package installable to any volume but test the System OS Version, your package is broken: The user will be able to install your software to a volume whose version of the OS cannot run it. You must use the Target OS Version.

As far as I know, there’s no way to make a package that does both properly, since the choice of any volume, booted volume only, or Home only is per-package, not per-choice or per-contents.

Dramatic twist ending

The above is good if you’re targeting Leopard. If you still support Tiger, there’s a twist. (Obligatory video link.)

GrowlMail is a good example. As a Mail bundle, it requires a couple of user-default settings to work. That makes installing to /Library pointless, because the settings will only be set for the user who installed it, so it won’t work for any other users on the system.

Leopard allows installing to ~, so that’s easy: I use System OS Version, as I suggested above.

But Tiger’s Installer can’t install to ~. The same Installer package that works on Leopard does not work on Tiger (I even tested with earlier betas—it has never worked in any 1.1.6 beta). I don’t know how nobody noticed this, not even our Tiger testers.

The Installer package for Tiger must target /Library, since I can’t do the proper thing on that OS version, so I must make separate GrowlMail packages for Tiger and Leopard.

  • The Leopard package installs to ~/Library and uses System OS version, as I suggested above.
  • The Tiger package installs to /Library and uses both Target OS Version and System OS Version:
    • If the user is running on 10.5 or later (System OS Version ≥ 10.5.0), the package tells them to use the other package. (The other package has a similar check.)
    • If a destination volume does not have 10.4 or later installed on it (Target OS Version < 10.4.0), the package tells them they can’t install there.

This is what you’ll find in Growl 1.1.6b4 and 1.1.6 final. It’ll go away in 1.2, since we’re dropping Tiger then.

The correct way to write a bug report in RadarWeb

Wednesday, July 15th, 2009

While I’m making screencasts of OmniWeb…

RadarWeb provide a JavaScript tool to fill in the section headers for their desired format automatically.
QuickTime/H.264, 960×538, 376 K

This is the format they want you to use, and since a few months ago, it’s now easy for you to use it.

My documentation viewer

Wednesday, July 15th, 2009

This is what I use to view Apple’s documentation:

My web browser.
QuickTime/H.264, 960×538, 1.3 MiB

The application is OmniWeb. I have a series of entry points bookmarked in the (hidden) Favorites bar:

(Someday, Carbon will perish from the list, the ones after it will move up, and another framework—probably either QTKit or Core Animation—will become the new ⌘8.)

And yes, those are all file: links.* Your web browser is perfectly capable of displaying web pages stored locally, and that’s all the Apple documentation is: locally-stored web pages.

With this arrangement, I can get to the reference information I’m looking for faster, and I can have multiple references (even multiple definitions) open at once because OmniWeb supports tabbed browsing.

Here are some other pages worth bookmarking:

You can use these and other bookmarks with a nice feature of OmniWeb which has also, more recently, appeared in Google Chrome: You can type any substrings from your bookmarks’ names and URLs into the address bar, separated by whitespace, and it will know what you mean. So, for example, I can type “kt kit”, and OmniWeb knows I mean “QuickTime Kit”; I simply hit return, and it takes me to that framework reference.

UPDATE 2009-09-07: Updated links to Snow Leopard’s docset name (where possible).

* On Leopard, change the docset name to com.apple.ADC_Reference_Library.CoreReference.docset.

Singletons in Cocoa: Doing them wrong

Wednesday, June 17th, 2009

UPDATE 2010-09-04: I wrote this post about an older version of Apple’s singleton example. The current version is much better: It still doesn’t handle over-releases the way I would like, but there’s nothing objectively wrong with it. As such, there’s nothing wrong with using Apple’s current example. You can continue reading this post to see my criticism of Apple’s old singleton example and my own implementation.


A singleton is a simple concept: It’s an object that you can only have one of. Being that simple, you may think it’s hard to get wrong.

If you do, I welcome you to the wonderful world of programming.

The Cocoa Fundamentals Guide is necessary reading for all Cocoa programmers. Even so, nobody’s perfect, and the CFG’s authors are no exception.

On Twitter last night, a mistake of theirs came to light when someone named Nick tweeted about how hard it is to make a singleton in Cocoa. Nick cited an example from the CFG; Chris Hanson responded that “that example does WAY too much work”, and Bill Bumgarner added that the example is “ridiculous”. They‘re were both right.

Doing it wrong.

The example, in order to “ensure singleton behavior”, overrides four basic Foundation methods:

  • retain
  • release
  • autorelease
  • retainCount

In the override implementations, retain, release, and autorelease are all no-ops. release does exactly nothing; the other two do nothing but return self. The override implementation of retainCount unconditionally returns UINT_MAX.

Before I proceed any further, I’ll give you a caution about singletons. You generally do not need to make your object a singleton at all. Even if your application has a single-window interface, with only one of each controller, you probably don’t need to enforce that. Just don’t create more than one. Then, if you do create more than one, you have a bug.

Let’s digress for a moment. Imagine if you allowed it. Imagine that you allow, say, your app delegate to create more than one of your root controller object. Your app delegate will then proceed to set up both twin objects, and they both respond to such things as notifications.

Bad, right? Now let’s say you “fix” this by making your root controller a singleton.

Your app delegate is still trying to create two root controllers. It’s still trying to set up two root controllers, and as a result of the two set-up messages, the controller is signed up twice for notifications.

But now you really only have one root controller. Your app delegate creates the first one, then gets it again when it tries to create the second. All according to plan so far. Then your app delegate sets up the first object—and then it sets it up again, again thinking that it’s talking to a second object. Even worse, because the object is now signed up twice for notifications (once per set-up message), every notification response happens twice.

You now have only one root controller, but you didn’t fix the bug, which wasn’t in the controller at all, but in the app delegate. To fix the bug, you must fix the app delegate; you don’t need a singleton for this at all.

OK, digression over. Singletons are bad. Avoid them. If you have a lot of them, rip most of them out. (Dave Dribin has bookmarked a lot of other good cases against singletons, and BJ Homer points out that they aren’t all bad. More on BJ’s post later.)

Back to the singleton at hand.

First, let’s look at retainCount. A comment explains that UINT_MAX “denotes an object that cannot be released”, implying that the framework itself considers UINT_MAX a special value.

This is actually correct, although I originally thought (and wrote, in an earlier version of this post) that it was bogus. The documentation for retainCount explicitly says that objects whose release method does nothing should return UINT_MAX.

Next on the hit list: autorelease. This is just mostly pointless. autorelease means nothing more than “send this a release message later”. If release does nothing, then autorelease becomes “do nothing later”. All this override does is move the nothing up to now. A performance optimization, perhaps, but I’d say it’s premature.

And now we come to the real villains: retain and release.

First off, you shouldn’t retain a singleton anyway. I can’t imagine why you would do this, except incidentally, by making it a timer target or something.

But even if you do think of a reason to retain a singleton, you still need to balance retain and release. If you retain without releasing afterward, you are under-releasing the object. If you release without retaining previously, you are over-releasing the object. These two statements have no exceptions.

If you break retain and release, then you’re able to over-retain or over-release (or even both!) the object with impunity. Your app no longer crashes, but you didn’t really fix the problem; you’re just getting away with it. You’re still trying to over-retain and/or over-release an object.

The Cocoa Fundamentals Guide’s primary audience is new Cocoa developers. Those who have never used a retain-counting system before may very well over-release the singleton, and Apple’s example singleton implementation hides that bug from them. That’s bad; every Cocoa programmer should know how to recognize an over-release crash, and breaking retain and release denies the reader an opportunity to learn that. I’ve filed a documentation bug report about the example.

Also, a rebuttal

BJ Homer responds at a different angle to last night’s flurry of tweets.

First, though, we need to get a definition straight. A singleton is a class of which there should only be one instance in any given process. There are actually very few singleton classes in the Cocoa framework including NSDocumentController and NSFontManager. You cannot create more than one of these objects; …

This is true. A singleton object is an object that your app can only have one of. There are a couple of different ways to do this:

… if you try to call [[NSDocumentController alloc] init], you’ll get back the exact same object as you do when you call [NSDocument sharedDocumentController], no matter how many times you call alloc and init. NSApplication is arguably a singleton as well; you can alloc another one, but you’ll get an assertion failure when you call init.

Another way is to simply implement the sharedFramistan method, and leave allocWithZone: and init alone. I suspect that this is common, since it’s the easiest way, but BJ is right that it isn’t a true singleton, since it allows multiple instances.

Where BJ goes wrong is in his defense of the retain and release overrides:

Consider the following example:

MyFloozit *floozit1 = [[MyFloozit alloc] init];
[floozit1 doSomething];
[floozit1 release];

MyFloozit *floozit2 = [[MyFloozit alloc] init]; // MyFloozit is a singleton, so this should be the same object as floozit1
[floozit2 doSomething]; // CRASH HERE
[floozit2 release];

We’ll leave aside the problem that you probably should be using sharedFloozit to obtain the singleton instance of MyFloozit.

When floozit1 is set, a new MyFloozit is allocated, and a static MyFloozit pointer is set. When floozit1 is released, that static pointer is still pointing to the old instance. As a result, when we try to set floozit2 (or when anyone else tries to call [MyFloozit sharedFloozit]), we get back a pointer to that same instance. The one that has been dealloc-ed.

BJ is missing something else the CFG says, which he even quoted later on:

Situations could arise where you want a singleton instance (created and controlled by the class factory method) but also have the ability to create other instances as needed through allocation and initialization. …

(Emphasis added by me.)

A singleton object owns itself. As such, it retains itself. As such, it should never die, because it always has at least one owner—and that’s without breaking retain and release. If it does die, it’s because something over-released it; later, something that was using it will crash, which lets you know that you have a bug. This is a good thing, because now you can fix the bug.

Each of the release messages in BJ’s example balances an alloc message above it. That alloc message may actually return an existing object, but we’re expecting to own a new object. Therefore, the singleton’s allocWithZone: should implicitly retain the existing object.

There is no good reason to override retain and release. Don’t do it. This also goes for autorelease. And, since you never override release, you also never need to override retainCount.

Doing it right

So, having thoroughly dismantled the [old] Apple documentation’s poor implementation of a singleton, let’s look at the correct way to do it.

Let’s go through the requirements:

  • The One True Instance is the only instance. (If you deliberately allow multiple instances, I call this a “multipleton”. I’ll leave that as an exercise for the reader, and concentrate on the true singleton here.)
  • There is a sharedFramistan method. It tests whether the One True Instance exists; if not, it creates the object and remembers it in file-scope static storage. Then it returns the One True Instance.
  • We’ll allow going through alloc and init, and return the same instance. We’ll do this in allocWithZone:, as Apple did. We’ll also need to make sure init doesn’t do its work twice on the same object.

[UPDATE 2010-09-04: I used to have the code inline in the post here; I have since moved it to a Mercurial repository on Bitbucket. You can download PRHEmptySingleton.h and .m from there.]

This is actually even more complex than Apple’s example, but it passes all six of these tests:

  1. sharedFramistan always returns the same object.
  2. alloc/init always produce the same object (which, itself, is the same object as sharedFramistan).
  3. alloc/init will not return an object confused by multiple init messages.
  4. Over-releasing causes a crash.
  5. Keeping alloc/allocWithZone:/retain balanced with release never causes a crash.
  6. If [super init] returns a different object, alloc/init won’t break.

Apple’s [old] example fails test 4. BJ doesn’t show an implementation for his example, but according to his own description of its behavior, it fails test 5. My version passes all six.

Take-aways

Hiding bugs is bad. Even worse is giving code that can hide a bug to new Cocoa programmers who could really use practice in detecting and fixing that kind of bug.

If you really need to implement a singleton, there is a right way to do it. The way currently shown in the Cocoa Fundamentals Guide isn’t it.

Don’t change the behavior of retain, release, retainCount, or autorelease. Ever.

UPDATE 2009-09-04: Removed hasInited instance variable after Christiaan Hofman pointed out its redundancy in the comments.

UPDATE 2009-09-19: Moved assignment of the sharedInstance static variable from +initialize to -init, as suggested by Uli Kusterer.

UPDATE 2010-09-04: Replaced inline code sample with links to the Mercurial repository for the sample.