Joris Kluivers

I like to build software.

Tracking AppleScript Progress in Yosemite

The Yosemity update for OS X brings several advances in OS automation. A few people have written about this already, and as usual Michael Tsai provides a nice overview.

New in AppleScript is the ability to report progress. This enables the Finder or other UI in Yosemity to show progress indicators while your script is running.

1
2
3
4
5
6
7
8
set n to 10

set progress total steps to n

repeat with i from 1 to n
  delay 1
  set progress completed steps to i
end repeat

Script editor will run this script and show it’s progress at the same time:

Reporting progress in AppleScript looks very similar in usage to the NSProgress class introduced in iOS 7 and OS X 10.9.

The NSProgress class provides a self-contained mechanism for progress reporting. It makes it easy for code that does work to report the progress of that work, and for user interface code to observe that progress for presentation to the user.

Not only does NSProgress provide a way to transparently handle progress within the same process, it also works between processes. I’ve used this before in a simple command line utility to report it’s progress to any UI wrapped around it.

A small demo app I wrote proves AppleScript is using NSProgress as well, making it very easy to observe AppleScript progress in your own software. Even when that script is executed outside of your sandbox using NSUserScriptTask.

It doesn’t require a lot of additional code to get this working:

1
2
3
4
5
6
7
8
9
[NSProgress addSubscriberForFileURL:scriptURL withPublishingHandler:^NSProgressUnpublishingHandler(NSProgress *progress) {
    self.progress = progress;
  
    // in the demo app the fractionCompleted property of the progress instance is observed by a progress bar using bindings

  return nil;
}];

// run your script using NSUserScriptTask for example

It’s good to see NSProgress being adopted in different parts of the OS. However because the class is still relatively unknown it is not always clear where it’s functionality is available.