Archive for the 'Programming' Category

Symbolicator 1.0.1

Friday, April 24th, 2009

It’s two-thirds faster, it works on more crash logs, and thanks to Augie Fackler, it’s now available from the Python Package Index. This means that you can just do this:

sudo easy_install symbolicator

If [you run a custom build of Python and] you don’t want to install setuptools, you can always get the Symbolicator from its webpage.

Oh, and there will be a 1.0.2 to fix some issues. At the moment, I’m going back to working on Growl things, so I won’t start on those for awhile; if you want to beat me to them, fork the project on Bitbucket, commit your fixes, and send me a pull request. (Make sure you co-ordinate your efforts on the ticket! I don’t want to have to choose from two independently-developed fixes.)

UPDATE 2009-04-25: Clarified above that installing setuptools is only necessary if you have installed Python yourself. Thanks to Augie for pointing this out in his comment.

How to make hg merge, hg resolve use FileMerge

Wednesday, April 22nd, 2009

Put this in your ~/.hgrc file:

[merge-tools]
filemerge.executable=opendiff
filemerge.args=$other $local -ancestor $base -merge $output
filemerge.gui=True

(Based on the original description of and Matt Mackall’s comment on a Mercurial bug about merging.)

New tool: The Symbolicator

Sunday, April 19th, 2009

The most significant behind-the-scenes change in Growl 1.1.5 is that we now build using the DWARF-with-dSYM debug symbol format.

Now, we distribute a fully-stripped executable for every release—even betas—and we keep the dSYM bundles on hand separately. The idea here is that we can use the dSYM bundles to obtain symbolic information (function name, filename, and line number) for the bare addresses in users’ crash logs.

Unfortunately, there are no good tools for symbolicating Mac OS X crash logs. If this were an iPhone app, we could just drag the crash logs into the Xcode Organizer window, but Xcode doesn’t do this for Mac crash logs.

I tried all the other tools as well, and every one of them had one of two problems:

  1. Didn’t work at all
  2. Needed the dSYM bundle and main bundle to be next to each other on disk

#2 is not a deal-breaker, but it is a hassle.

So I wrote my own symbolication tool.

The Symbolicator is a Python script that:

  1. Reads in a crash log.
  2. Finds the necessary dSYM bundles using Spotlight. (This means that you can put the dSYM bundles anywhere you want, and as long as Spotlight can find them, the Symbolicator will be able to use them.)
  3. Uses dwarfdump to extract the relevant symbol information.
  4. Replaces the address offsets with the symbol information (just like CrashReporter does when it has debug symbols to work with).
  5. Writes the symbolicated log to stdout.

Use it like this:

% symbolicator < unsymbolicated.crash > symbolicated.crash

Or use ThisService to make a service out of it.

If you want to see it in action right now, download Growl 1.1.5b1 and the corresponding dSYM bundles from the Growl beta page. Make Growl crash (killall -TRAP works well), then unpack the bundles and use the Symbolicator on the crash log. (If you unpack the bundles first, CrashReporter will symbolicate the log before you even get to it. Handy, unless you’re trying to test the Symbolicator. ☺)

To make this work on your own app, follow the instructions in the aforementioned ADC article, then make sure you archive the dSYM bundles for every release, including betas. On Growl, I added code to our Release Makefile for this.

Note: If your app is closed-source, you should not put your dSYM bundles on your website, since the debug symbols are arguably trade secrets (information about your source code). Keep them locally, perhaps on a flash-memory drive. Disclaimer: IANAL.

Manpage Monday: PlistBuddy(8)

Monday, April 13th, 2009

PlistBuddy(8) is a command-line tool for editing property-list files, with a deeper reach than plutil defaults:

Entries consist of property key names delimited by colons. Array items are specified by a zero-based integer index. Examples:

  :CFBundleShortVersionString
  :CFBundleDocumentTypes:2:CFBundleTypeExtensions

Jonathan “Wolf” Rentzsch, in his del.icio.us bookmark for the manpage, says that PlistBuddy is “always at /usr/libexec/PlistBuddy on modern systems”.

Don’t pass objects as context pointers

Friday, April 3rd, 2009

Cocoa has several functions and methods that run a panel (usually as a sheet) asynchronously. These functions and methods take a target object, a selector, and a context pointer, and when they finish, they send a message to the target with that selector, passing that context pointer.

A common practice is to pass an object in the context pointer. You retain the object before you call the run-panel function or method, then release it in your callback. For example:

    NSBeginAlertSheet(/*title*/ NSLocalizedStringFromTableInBundle(@"Update Available", nil, bundle, @""),
                      ⋮
                      /*modalDelegate*/ self,
                      /*didEndSelector*/ NULL,
                      /*didDismissSelector*/ @selector(downloadSelector:returnCode:contextInfo:),
                      /*contextInfo*/ (void *)downloadURL,
                      …);

In this example, downloadURL is a local variable, and the object in it was retained above, or maybe not autoreleased in the first place. The downloadSelector:returnCode:contextInfo: method will cast the context pointer back to an object type, probably do something with it, then release it.

This has recently become a visible problem because of the Clang Static Analyzer. The analyzer doesn’t know that NSBeginAlertSheet will retain the object, so it flags this call as a leak. This is the most-often-cited example of the checker’s “false positives”: things that it flags as bugs but that aren’t really bugs.

But is it really not a bug? Is it really appropriate to use an object as a context pointer?

Let’s think about what we’re doing here:

  1. The panel doesn’t know the context pointer is really an object, so it doesn’t retain it. To compensate for this, we’re retaining an object on behalf of another object (the panel). This alone should make you feel dirty.

  2. The panel doesn’t know the context pointer is really an object, so it won’t release the object, either. This is particularly a problem if something releases the panel (quite possible in the case of, say, an NSAlert instance). Then it really is a leak.

  3. If we get released (and, hopefully, take the panel with us or at least cancel it), then we leak the object, because we are only expecting to have to release it (or even to have access to it!) in the callback.

Passing objects through context pointers is an anti-pattern. I hope the Clang Static Analyzer developers never remove this warning, because this is not a false bug—it is a real bug that we should all fix in our programs.

Solutions

That object needs to go in an instance variable somewhere.

The lightweight solution is to create an instance variable on the object that is running the sheet. You store the object in the instance variable when you run the sheet (and leave the context pointer NULL), then retrieve the object from the instance variable in your callback. You’ll still need to retain it when putting it in, and release it both in your callback and in dealloc—those aspects don’t change.

I can hear you saying that this is a waste of an instance variable. What are they, rationed? There’s nothing to waste; instance variables are cheap. And leaking objects is far more of a waste of memory than adding an instance variable.

But this isn’t the only solution.

Another way is to create your own subclass of the panel class (NSOpenPanel, NSSavePanel, or NSAlert), and give the subclass a property you can use instead of the context pointer. You could make it abstract (making the property similar to NSMenuItem’s representedObject, nothing more), or make it specific to your application. The former approach is simpler, whereas the latter gives you a base on which to build a more-customized alert if you later decide you want one. It’s up to you.

The advantage of this solution is that, since you’ve formalized the instance variable as part of a class’s API (and since the instance variable is no longer a bit player but the central part of a class), it’ll be harder for you to forget to manage your ownership of it correctly. Memory problems solved.

One way or another, though, you need to put that object into an instance variable somewhere to avoid leaking memory, feeling dirty, and having the Clang Static Analyzer chew you out.

(And yes, all this applies with garbage collection as well. See the section “GC Gotchas” in episode 36 of Late Night Cocoa, but I disagree with Andre Pang’s recommendation of CFRetain and CFRelease; the right solution is not to dip into Core Foundation, but to avoid the context pointer altogether and use an instance variable instead.)

hg precommit hooks and the Clang Static Analyzer

Friday, April 3rd, 2009

Fraser Speirs has a post about configuring your Git repository to vet commits with the Clang Static Analyzer.

The idea of pre-commit hooks is that you get to run a script before the commit happens. Depending on the result code of the script, the commit will either proceed or be aborted.

I wrote a wrapper around the scan-build tool, so that I could run the analyzer by hand with my preferred options at any time: …

The –status-bugs flag is the trick here: it makes scan-build return a non-zero status code if it detects bugs. That’s what we want with Git pre-commit hooks: a non-zero status indicates a possible bug, and that causes the Git commit to be aborted.

Mercurial, of course, has the same feature. The hg book has instructions; I’ll show you how I set up my repository to do this.

First, I created a shell script named RunClang.zsh:

#!/bin/zsh -f
~/bin/checker-latest/scan-build \
    -checker-cfref -warn-objc-methodsigs -warn-objc-missing-dealloc -warn-objc-unused-ivars \
    --status-bugs -o checker.out \
    xcodebuild -configuration $1

Next, I added my precommit hook to the repository’s .hg/hgrc file:

[hooks]
precommit.RunClang = ~/bin/RunClang.zsh Development

Here’s what an example session looks like:

% echo 'Testing precommit testing hook' >> test.txt
% hg ci -m 'Testing precommit testing hook'
[churn churn churn]
** BUILD SUCCEEDED **
scan-build: 17 bugs found.
scan-build: Run 'scan-view [snip]/growl-boredzo-precommit-test/checker.out/2009-04-03-2' to examine bug reports.
abort: precommit.RunClang hook exited with status 1

(255)% hg log --limit=1
changeset:   4188:b208862a586d
tag:         tip
user:        Peter Hosey
date:        Fri Mar 13 05:40:09 2009 -0700
summary:     Fix encoding of the Norwegian Growl-WithInstaller strings file.

17 bugs—mostly leaks. Glad I didn’t commit this test file!

So now you know how to have Mercurial block you from committing if the clang checker can find bugs. This should also work for your unit tests. And if you have 100% test coverage (lucky!), you can combine them: have scan-build build your test-bundle target. Then, the hook will prevent the commit if the checker can find bugs or any tests fail.

I don’t think I’ll actually use this set-up, though.

First, in order to find bugs, you need to build your entire main product. Any significantly large program is going to take a long time to build and analyze—Growl, for example, takes about one-and-a-quarter minutes for a clean build. Even committing to a Subversion repository over dial-up was quicker.

More significantly, precommit hooks like this interfere with patch queues. The mq extension implements patches as mutable commits, so any qnew or qrefresh will run the hook. It would be useful on qfinish, but it’s just annoying on qnew and especially qrefresh, as the all-too-frequent builds thwart rapid iteration.

So, if you use patch queues, this won’t work for you. But, if you don’t, then this should work as well in Mercurial as it does in Git.

Adding Growl support to Mercurial

Wednesday, April 1st, 2009

Add this to your ~/.hgrc file:

[hooks]
changegroup.growl = ((echo "$HG_URL" | grep -vF 'file:' > /dev/null) && growlnotify -n Mercurial 'Pull successful' -m "Pulled at least $(hg log --template='\n' -r$HG_NODE:tip | wc -l | sed -e 's/ //g') changesets from $HG_URL") || true
outgoing.growl = (test "x$HG_URL" '!=' 'x' && growlnotify -n Mercurial 'Push successful' -m "Pushed to $HG_URL") || true

It’s not perfect: Both notifications share the same notification name. As long as that isn’t a problem, this works fine.

Manpage Monday: copyfile(3)

Monday, March 30th, 2009

copyfile(3) is an API for copying and moving files within the file-system:

DESCRIPTION

These functions are used to copy a file’s data and/or metadata. (Metadata consists of permissions, extended attributes, access control lists, and so forth.)

The copyfile() function can copy the named from file to the named to file; the fcopyfile() function does the same, but using the file descriptors of already-opened files.

The copyfile() and fcopyfile() functions can also have their behavior modified by the following flags:

COPYFILE_CHECK

Return a bitmask (corresponding to the flags argument) indicating which contents would be copied; no data are actually copied. (E.g., if flags was set to COPYFILE_CHECK|COPYFILE_METADATA, and the from file had extended attributes but no ACLs, the return value would be COPYFILE_XATTR.)

COPYFILE_PACK

Serialize the from file. The to file is an AppleDouble-format file.

COPYFILE_UNPACK

Unserialize the from file. The from file is an AppleDouble-format file; the to file will have the extended attributes, ACLs, resource fork, and FinderInfo data from the to file, regardless of the flags argument passed in.

File Manager also has APIs for copying files, in both asynchronous and synchronous flavors. Those APIs don’t provide as much control over management of metadata, but they do offer asynchronous operation, whereas the copyfile(3) APIs appear to be synchronous.

And, of course, I should mention NSWorkspace operations, which you use with the performFileOperation:source:destination:files:tag:
method
. Unlike the other two, this API has been around since 10.0. On the other hand, like copyfile(3), it’s synchronous only.

Safari 4 beta and GrowlMail

Tuesday, February 24th, 2009

The problem

The WebKit framework that comes with Safari 4 enforces a restriction on calling WebKit from a secondary thread.

GrowlMail accesses message contents on a secondary thread because they may not be in yet. Accessing message contents can result in a call to WebKit. That results in a crash with the new WebKit.

The fix (section added 2009-04-19, updated 2009-06-22 for the 1.1.5 release)

Download Growl 1.1.5 and install GrowlMail 1.1.5.
(Make sure you install GrowlMail specifically! The Growl Installer package does not include GrowlMail or any of the other Extras.)

The workaround

UPDATE 2009-06-22: You don’t need to do this anymore. Install GrowlMail 1.1.5 instead.

If you’re fast or can easily turn off your internet connection first, go to GrowlMail’s Preferences and set GrowlMail to summary mode. (You might also try putting Mail into Offline mode immediately after launching it until you’ve made this change.)

  1. Go to Mail’s Preferences.
  2. Click on the chevron button at the far right end of the toolbar.
  3. Click on GrowlMail.
  4. Choose the second of the three radio buttons: “Show a summary of received emails”.

You can then go back into online mode/turn your internet connection back on/rest easy.

The other way to do it is to run this command in a terminal window:

defaults write com.apple.mail GMSummaryMode -int 2

Ordinarily, I’d tell you to quit Mail first, but since Mail will unexpectedly quit the first time tries to Growl about a new mail message, I don’t think I need to bother. ☺

The fix

We’re not sure about that yet.

The problem is that when Mail adds a new message to your library, it may not have fully downloaded it yet. (You can see this yourself sometimes when your internet connection is slow or under heavy load: You’ll click on a message and see a “Loading” screen in the preview pane.)

When that happens, if we try to get the message body on the main thread, it blocks the UI until the body arrives. So we do it on a secondary thread instead. That’s now a problem.

The ideal fix is that we find a way to determine whether the body has come in yet. If it hasn’t, we could set a timer for a few seconds, then check again then and post a notification with “body not loaded yet” if it’s still not in.

Another fix I would consider is simply killing the feature that shows the message body in the notification. I’m sure a lot of you like it, but if it breaks the app and there’s no fix, then it has to go.

UPDATE 2009-02-25: As it turns out, we had most of the above fix in already (except that we were using a delay, not a timer—not a problem, since it’s on its own thread). So the fix was simply to move most of the code to the main thread. I’ve done that and it works. The relevant patches are pending review; if I hear nothing bad about them from the other developers by tomorrow, I’ll make them permanent commits and push them to both repositories, where they will be part of 1.1.5.

Other points

This is not a bug in WebKit. Strictly speaking, it’s not a bug in GrowlMail, either, because it’s not like we’re disobeying the documentation for Mail’s API (there is none!).

Apple changed WebKit to throw this exception, and GrowlMail doesn’t catch it. As far as I’m concerned, it’s GrowlMail’s fault and we’re the ones who need to fix it.

Timeline? No idea. I do intend to have this fix in for 1.1.5, since Safari 4 will probably be either out or coming Real Soon Now by then. (This among other important fixes, such as the off-by-two error in the Growl prefpane.)

UPDATE 2009-06-22: The fix is in GrowlMail 1.1.5, which we released on 2009-06-16.

Why the compiler won’t let you declare a variable immediately after a case

Friday, February 20th, 2009

Consider this code:

enum { foo, bar, baz } my_var;
switch (my_var) {
    case foo:
        int foo_alpha; //Line 7
        int foo_beta;
        break;

    case bar:
        my_var = baz;
    case baz:
        printf("Bar or baz encountered\n");
        break;
}

Try to compile it as C99.

Here’s what GCC says:

test.c: In function ‘main’:
test.c:7: error: syntax error before ‘int’

What!

First off, why not? What is invalid about this declaration statement?

Second, why is foo_alpha invalid and not foo_beta?

There are several definitions in the C99 specification that come together to cause this problem.

The first is that there is no such thing as a declaration statement, because declarations are not statements. See §6.7 and §6.8; note that neither definition includes the other. In the language that is C99, declarations and statements are separate concepts.

The second is the definition of a compound statement. The definition of a switch statement (which is part of §6.8.4) is:

switch ( expression ) statement

If you go back up to §6.8, you’ll see that another possible kind of statement is a compound statement, for which §6.8.2 gives this definition:

compound-statement:
  • {   block-item-listopt   }
block-item-list:
  • block-item
  • block-item-list   block-item
block-item:
  • declaration
  • statement

So a declaration is not a statement, a compound statement can contain declarations and/or statements, and a switch statement is a prefix upon (usually) a compound statement.

Now, the kicker. Read the relevant definition of a labeled statement from §6.8.1:

case   constant-expression   :   statement

Statement. Not block-item. Not declaration. Statements only.

So this is what the compiler sees in valid code (with a declaration not following a case label):

  • selection statement (switch)
    • compound statement
      • labeled statement
        • statement
      • statement
      • statement
      • declaration
      • statement
      • jump statement (break)
      • labeled statement
      • statement
      • jump statement (break)
      • labeled statement
      • statement
      • jump statement (break)

Now, consider how the compiler sees my code above:

  • selection statement (switch)
    • compound statement
      • labeled statement
        • declaration — wait, this isn’t a statement! ERROR
      • declaration — also a kind of block-item, so it’s perfectly valid here
      • jump statement (break)
      • labeled statement
      • statement
      • labeled statement
      • statement
      • jump statement (break)

I hope this makes clear that this isn’t a compiler bug; the C99 language really does work this way.

(One possible solution would be to make a declaration a kind of statement, but I don’t know what other ramifications that might have. [UPDATE 11:36: Jeff Johnson tells us why not.])

Manpage Monday: CC_SHA(3cc)

Monday, February 16th, 2009

The Common Crypto library in Mac OS X 10.4 and later provides simple APIs for five SHA algorithms:

CC_SHA1() computes the SHA-1 message digest of the len bytes at data and places it in md (which must have space for CC_SHA1_DIGEST_LENGTH == 20 bytes of output). It returns the md pointer.

CC_SHA1_Init() initializes a CC_SHA1_CTX structure.

CC_SHA1_Update() can be called repeatedly with chunks of the message to be hashed (len bytes at data).

CC_SHA1_Final() places the message digest in md, which must have space for CC_SHA1_DIGEST_LENGTH == 20 bytes of output, and erases the CC_SHA1_CTX.

The successor versions of SHA-1, SHA-2, are also implemented for hash bit lengths of 224, 256, 384, and 512. The functions to call to invoke the larger hash-size versions of the algorithms include the hash size as part of the function names: …

RETURN VALUES

All routines return 1 except for the one-shot routines ( CC_SHA1(), etc.), which return the pointer passed in via the md parameter.

How ClickToFlash works

Thursday, January 29th, 2009

Speaking of everybody’s favorite WebKit plug-in, here’s how it works. This should help you understand how it fails on some sites, and maybe aid you in contributing to its development.

First off, it is a WebKit plug-in; it’s written in Cocoa and uses WebKit’s own plug-in API. It does not use the Netscape plug-in API.

A WebKit plug-in declares a list of MIME media types in its Info.plist bundle. It does this by way of a dictionary of dictionaries:

<key>WebPluginMIMETypes</key>
<dict>
    <key>application/x-shockwave-flash</key>
    <dict>
        <key>WebPluginTypeDescription</key>
        <string>ClickToFlash</string>
    </dict>
</dict>

WebKit only loads a WebKit plug-in when it first encounters some content that it needs the plug-in for. It uses these Info.plist dictionaries to know which plug-in it needs to load. So, in the case of ClickToFlash, it only loads ClickToFlash when it encounters something that is of type application/x-shockwave-flash.

Here’s the brilliant part. Adobe’s Flash Player plug-in actually declares* two MIME media types: application/x-shockwave-flash and application/futuresplash.

You will notice that ClickToFlash only declares one of these.

As it turns out, everybody only uses application/x-shockwave-flash. ClickToFlash exploits this.

When you click on the ClickToFlash view, it modifies the object or embed element that the view represents, changing its type attribute to the other type—the one ClickToFlash doesn’t declare; the one no webpages actually use. WebKit notices this change and looks again for a plug-in to handle the movie. This time, it comes up with only one handler: the real Flash Player plug-in.

There are several reasons why a site may not work with ClickToFlash. I suspect one reason is that they try to interact with the movie via JavaScript; ClickToFlash doesn’t export a script object and wouldn’t be able to communicate with the real Flash Player anyway. The script finds itself talking to a wall, and breakage happens.

So now that you know how ClickToFlash works, maybe you can help fix its bugs?


* Flash Player doesn’t declare its MIME types in its Info.plist; it declares them in a resource file, in ‘STR#’ resource 128. Thanks to WebKit developer Mark Rowe for reminding me to look for a resource.

iPhone app settings

Wednesday, January 7th, 2009

One of the ongoing debates among users of iPhone OS devices is whether an app’s settings belong in the app itself, or the Settings app.

I’m of the opinion that this wouldn’t even be a debate if it weren’t for Apple’s prescription in the iPhone HIG that every iPhone app’s settings should be in the Settings app. Mac apps don’t come with prefpanes for their preferences (with the exception of faceless background apps like Growl). Windows apps don’t, either, that I know of. GNOME and KDE apps don’t pollute Ubuntu’s Control Panel.

The iPhone is the only OS I know of whose developer recommends that app developers put their application settings in the system-wide Settings app.

As we’ve seen several times on every platform, it’s OK to break one of the local Human Interface Guidelines if and only if the violation makes the interface better.

I think this guideline is one that iPhone developers should violate flagrantly.

But there’s a problem. The iPhone doesn’t really have an icon for a Settings button. Most developers seem to use the Info icon that one of the frameworks apparently provides, but this isn’t the proper use of that icon. The Info icon means info, not application settings.

Another choice is the gear icon for Action buttons:

NSActionTemplate.

But, again, we have a conflation of functions. The button in question is not an Action button; it is a Settings button. This icon is not a Settings icon. (I suspect that most people who use the Action icon use it because it doesn’t have any particular association with “action”, either, other than Apple’s endorsement of it for that.)

The Iconfactory, wisely, chose differently in Twitterrific. I suspect that this was largely coincidence, as the Mac version of Twitterrific came first and already had a Settings icon; for the iPhone version, the developers simply used the same icon. It works well enough:

as seen in this screenshot of Twitterrific.

But it’s not perfect. A wrench does not say “settings”. (I offer myself as evidence: When I first saw it in the Mac version, I didn’t know it was the Preferences button.) Generally, a wrench means “edit this”, as in the context of a game.

What we need is an icon that says “settings”. Ideally, this icon should either convey the notion of a changeable state value (as the previously-favored light switch [Mac OS X through Tiger] and slider [Mac OS] did), or build on an existing association with the concept of settings.

Let’s go with the latter. I nominate the Settings app’s icon:

iPhone Settings icon

Familiar enough, wouldn’t you say?

That’s Apple’s version. Here’s my button-icon (a.k.a. template) version, in the 16-px size:

Settings button icon 16-px version.

I tried it out in the iPhone version of Twitterrific on my iPod touch. Before and a mock-up of after:

Before.
After.

After I created this icon, I wondered what it would look like in the Mac version of Twitterrific.

Here’s the original:

…with the wrench icon.

… And right away we have a problem. These buttons are already framed; my white frame will glare here.

Fortunately, that’s easy to solve. With ten seconds of work, I created a frameless version. Here’s what that looks like:

Twitterrific-Mac-newSettingsIcon.png

I think we could all get used to this icon. This wouldn’t have worked at all before Apple changed the icon of System Preferences to match the iPhone Settings app, but now it can.

I don’t think it’s perfect. Perhaps a real icon designer (I’m just a programmer) can refine it. But I think it’s a good first draft. I’m curious to hear your opinions; please post constructive feedback in the comments.

If you want to use this icon, go ahead. Here’s the original Opacity document , from which you can build all the many variations of the icon. (Click on Inspector, then Factories, then find the version you want in the list and click its Build button.)

My CocoaHeads unit testing presentation

Monday, January 5th, 2009

One of the things that’s been keeping me busy lately (too busy, in fact, to keep up Framework Friday and Manpage Monday—sorry about that, and I’ll get back to them when I can) is preparing a video based on the presentation I gave at CocoaHeads last month.

I have now finished it. Its title is simply “Unit testing”.

The subject is unit testing for applications written in Cocoa to run on the Mac. I’m not an iPhone developer, so the video is only generally applicable to iPhone development (as much as it is to any other platform); for specific information about testing on the iPhone, see Colin’s blog post.

I corrected a few things that I got wrong in the original live presentation, and added a few new slides. Other than that, it’s basically the same.

The video is 13+½ minutes long (strangely, about half the length of the original live presentation), and is available in high-definition. You can even download the original file I uploaded, in case you’re so inclined; it uses the lossless Animation codec for the video track, and is 720p and 135.7 MiB.

I used several Creative Commons photographs in the slides. Here are the links back to them:

In other news, I love Keynote’s Instant Alpha feature.

Manpage Monday: notify(3)

Monday, December 8th, 2008

notify(3) is a simple API that allows processes to poke other processes, and to be poked.

The API is similar to NSDistributedNotificationCenter, except that it’s not object-oriented, it’s not based on Foundation or CF, and it doesn’t allow you to attach a property list to the notification.

You register in one of four ways:

notify_register_check
Sign up under a name, and get a registration token.
notify_register_signal
Have the system send your process a signal when another process posts a notification with a particular name. Also get a registration token.
notify_register_mach_port
Have the system send your process a message on a Mach port when another process posts a notification with a particular name. Also get a registration token.
notify_register_file_descriptor
Get a registration token, and have the system write that token to a file descriptor when another process posts a notification with a particular name.

Each of the last two functions will create the Mach port or file descriptor for you, unless you tell it to use one you already have. You do that by passing NOTIFY_REUSE.

All four functions give you a registration token (the first one does nothing else), which is simply a signed 32-bit integer. You can then use notify_check to poll that token to see whether any processes have posted a notification to it since the last time you checked. (I don’t know how the other notification methods affect this—e.g., whether notify_check will ever return true if you got the token from notify_register_signal.)

You free the token using notify_cancel. This also closes any Mach ports or file descriptors you have associated with it. There is no way to disassociate them from the token or to cancel the token without closing the associated resources.

On the sending side, the API provides one function: notify_post. It takes one argument, which is the notification name; this is the same name that any receiving processes passed to their chosen notify_register_whatever function.

Leopard adds a new feature: you can associate a shared 64-bit number with a name using notify_set_state, and retrieve that number using notify_get_state. I suggest that you only use notify_set_state in a single process, as I can imagine race conditions occurring if two processes try to set state under the same name. If you need bidirectional communication, use two notification names (or a different means of communication, such as sockets or Mach ports).

Apple introduced the rest of the notify(3) API in Panther.

Updates to “How to work with a bound-to array”

Wednesday, December 3rd, 2008

Following an email conversation with Dave Dribin, I’ve updated my earlier post on how to work with a bound-to array.

The most critical update, and the reason for a new blog post to announce the update, is that you should not currently implement addObject: and removeObject: for an array property. KVO has a bug where it treats these as set accessors, even if the property is an array. This will result in crashes if you observe your object using plain KVO.

The workaround is to use indexed accessors:

[self insertObject:newFramistan inFramistansAtIndex:[self countOfFramistans]];

This is a little uglier than addFramistansObject:, but it doesn’t crash.

The other update is that you need to implement both accessors in a pair. For example, for insertObject:inKeyAtIndex: to work, you must also implement removeObjectFromKeyAtIndex: (and vice versa). Otherwise, KVO won’t override the one you did implement, so you won’t get notifications for it.

I’ve filed bugs for both of these, and I’ve linked to both bugs from the older post.

How to work with a bound-to array

Wednesday, November 26th, 2008

You have a model object with an array property:

@property NSArray *framistans;

You also have an array controller whose contentArray binding is bound to this property.

How do you add an object to the array?

Wrong #1: Direct manipulation

[framistans addObject:newFramistan];

The array controller will not notice this change. Worse, the value of your array no longer matches the value your array controller last saw. (For one thing, your array is now one object longer.)

Wrong #2: Use the array controller’s add: action

[arrayController add:nil];

This works, but now you need to go looking for that object. The proper way would be to get the binding info for the array controller’s contentArray binding, then ask the bound-to object for its array, and get the lastObject of that array.

More likely, you’ll hard-code knowledge of which object and which property it’s bound to. Good luck when you change the binding!

Oh, and in a model object, this breaks the separation between your model and everything else. Your model should know nothing of your UI, so that you can replace the UI wholesale if ever you want to (for example, if you make a CLI or web-based version of your app) and keep the same model.

Wrong #3: Add the object to the array controller’s content array

newFramistan = [arrayController newObject];
[arrayController addObject:newFramistan];

This works, and at least you already have the object on hand. But you’re still giving your model knowledge of the array controller, so you’re still breaking separation.

Almost right: Add it to the mutableArrayValue for your property

[[self mutableArrayValueForKey:@"framistans"] addObject:newFramistan];

This works, and it’s clean.

The only problem with it is that it’s too heavyweight: you’re creating this proxy object just to mutate a property. The most appropriate use for mutableArrayValueForKey: is if you want to pass a mutable array to another object, and you want that array to actually be a property of another object. This is a very rare case—I’ve never needed to do it.

For this problem, there is a better solution.

The Right Way: Use your accessor

UPDATE 2008-12-02: Don’t do this. See the section I added below.

[self addFramistansObject:newFramistan];

Look at that.

Beautiful, isn’t it?

It’s almost as short as the direct array access, and it does the Right Thing with KVO. Your array controller will find out about the change without you having to tie knowledge of the array controller into your model.

We should also look at the accessor:

- (void) addFramistansObject:(Framistan *)newFramistan {
    [framistans addObject:newFramistan];
}

Also short, and also beautiful. (Yes, that is the complete definition of the method. I’m not eliding anything.) And there are no separation violations here, either: It’s pure model.

When you bind the array controller to your object, KVO wraps your object and all its KVC-compliant accessors, including this method. Its implementation performs the proper KVO notifications around a call to your implementation, which means you don’t have to do any KVO work at all.

UPDATE 2008-11-30: Note that you must also implement removeKeyObject:; if you don’t, addKeyObject: will not post the KVO notifications. You must implement both. Thanks to Dave Dribin, who emailed me about this.

ADDED 2008-12-02: The current Right Way: Use indexed accessors

KVO does not work correctly with addKeyObject: and removeKeyObject: for array properties.

The problem is that it treats those methods as set accessors and posts set-mutation notifications, regardless of the fact that it’s an array property. This doesn’t seem to cause a problem with Bindings (as of 10.5.5), but when I tried observing the property using KVO directly, I got a crash every time, as it tried to send NSSet messages to my NSArray.

Instead, you’ll need to use indexed accessors:

[self insertObject:newFramistan inFramistansAtIndex:[self countOfFramistans]];

As with addObject: and removeObject:, you must implement both of the pair. Here’s what removal looks like:

[self removeObjectFromFramistansAtIndex:[self indexOfObjectInFramistans:framistanToRemove]];

indexOfObjectInKey isn’t actually something KVC looks for, but it fits the use case and beats getting the entire array (which generally means copying it) just to find the index of one object. And you have to implement all these methods anyway.

Note that you should not implement addKeyObject: and removeKeyObject: at all for an array property, even to call the indexed methods. That’s because KVO always posts its erroneous set-mutation notifications around your addKeyObject: and removeKeyObject: methods, regardless of how you implemented them.

Thanks again to Dave Dribin, as most of this came up in the same email thread.

Further reading

Manpage Monday: afconvert(1)

Monday, November 24th, 2008

afconvert is a command-line utility that uses Core Audio to convert audio files from one format to another.

The manpage is actually pretty sparse (like the rest of the Core Audio documentation); you’re better off reading the command-line help:

% afconvert -h

A simple example is to convert an AIFF file to AAC in an MPEG-4 file:

% afconvert -f 'm4af' -d 'aac ' -b 98304 Recording.aiff

The resulting file is 96 kbps (98,304 bps) and is named “Recording.m4a”.

UPDATE 2008-11-26: Corrected permalink and title to include the section number.

New service: Insert Mac OS X Build Number

Friday, November 21st, 2008

File: InsertMacOSXBuildNumber.zip

A service that inserts the build number (for example, 9F33) of your current Mac OS X installation.

The main purpose for this is so that, when filing bugs in Radar, you can precisely specify which build of Mac OS X you’re running. (Especially if you’re running a pre-release build of a future version of Mac OS X.)

I created it with ThisService, of course.

(And yes, I am also working on tonight’s Framework Friday post.)

Report-an-Apple-Bug Friday! 75: NSUserDefaults and /Library/Preferences

Friday, November 14th, 2008

This bug is NSUserDefaults does not look in /Library/Preferences. It was filed on 2008-11-14 at 23:09 PST.

(more…)