AppleScriptObjC and Mavericks in Xcode projects


In OS X 10.9, AppleScript introduces an alternative syntax for calling handlers and methods. Instead of using underscores and running the terms together, like this:

 theString's writeToFile_atomically_encoding_error_(thePath, true, current application's NSUTF8StringEncoding, missing value)

You use an interleaved syntax similar to Objective-C, like this:

 theString's writeToFile:thePath atomically:true encoding:(current application's NSUTF8StringEncoding) |error|:(missing value)

There are some details you need to understand to make the transition smoothly.

The most important fact is that either syntax will work, as of Xcode 5.0.2, except in the case of action handlers. For action handlers, you must use the underscore syntax for Xcode to recognize them, so that you can link controls to them. Once a link is made, the syntax no longer matters.

Note that if you use ASObjC Explorer as an external editor to Xcode, as of version 3.0.7 it can automatically convert single-argument handlers to underscore syntax each time you save, to work around this problem.

If you enter your code in the old style, it will usually be converted when you compile. Usually — because the new syntax requires the call to be preceded by either the possessive form of a variable, like theString's above, or the term its. So if you have just an underscore-style method call, say in a tell block with no target in the statement itself, it will remain in underscore form.

The interleaved syntax also increases the likelihood of clashing with AppleScript terms: error will be a common case, and you need to remember to add pipes. The compiler adds them for you when recompiling underscored method calls. You also need to put parentheses around many arguments.

If you open a compiled script, whether saved using the interleaved syntax under 10.9 or the underscore syntax in earlier versions of the OS, it will open and compile according to the OS you open it under. In this sense, there is full backwards compatibility.

However, Xcode saves its files as .applescript files, and these are forwards compatible — you can open an underscore-styled file and it will compile and run fine under 10.9 — but not backwards compatible. For .applescript files, once they contain interleaved syntax, they will not compile under previous versions of the OS without considerable editing.

So if you need the ability to move Xcode projects between versions of the OS including 10.9, you need to consider saving compiled versions of your script. One way to do this is to make sure your debug build style has Save as Execute-Only turned off under OSA Compile build options. You can then use the compiled script from your debug builds. But it is is probably safer to save an explicit copy elsewhere, so you know it is the latest version.

The other thing you should keep in mind is that Xcode does not change the code you see by compiling it. So if you add new code, using interleaved terminology, it will live happily alongside code that uses underscore syntax. This can be confusing, to say the least.

The best advice is to always use an external editor to edit your Xcode projects, subject to the caveat above about action handlers. That way it is also easy to save a compiled copy if you think you will need to work on the project under an earlier version of the OS.

Mavericks also requires Xcode 5, which is not drastically different to Xcode 4.x. Keep in mind that the ability to save projects that use garbage collection will disappear soon, so if you need to keep maintaining applications that work on versions of the OS before 10.8, you should check before you upgrade Xcode beyond 5.0.2, and consider keeping a copy of version 5.0.2 for such use. Better still, you might keep a 10.8 startup partition or disk for such an eventuality.

If you do decide to turn garbage collection off, remember to turn Automatic Reference Counting on at the same time.

Also, Xcode 5 no longer supports the GCC compiler, which was selected in the sample projects because at the time it was needed to work around a problem in Apple's compiler. You may need to go to Build Settings and change the compiler (set it to use the default compiler).

Last, if you use the new use command, remember that the resulting application will run only under Mavericks or later.