MacOS – AppleScript “delay” command not working since switch to Yosemite

applescriptmacos

Note: The issue with delay was fixed in OS X 10.11 El Capitan.

Ever since I upgraded to Yosemite, Applescripts that use delays have stopped working. How can I fix this?

Here's the world's simplest Applescript, for the sake of an easy example:

set volume output volume 0
delay 5
set volume output volume 20
delay 5
set volume output volume 0
delay 5
set volume output volume 20
delay 5
set volume output volume 0
delay 5
set volume output volume 20
delay 5
set volume output volume 0

That should take 30 seconds to complete. If I run it in Script Editor (formerly Applescript Editor) it takes 30 seconds to complete. But if I save this script as an app, when I launch the app, the delays are ignored and the app takes a fraction of a second to complete.

How can I force Applescript to delay for a specified amount of time before moving on to the next step? Is this a Yosemite glitch? Is there a reliable workaround?

Best Answer

Note: The issue with delay was fixed in OS X 10.11 El Capitan.

@2oh1, you have the right basic idea in your answer, but here's a complete and correct answer:

The only reasonable way to work around this is to invoke "delay" within a loop that ensures the desired duration elapses before continuing. The best way to do this is to override "delay" with a custom handler:

on delay duration
  set endTime to (current date) + duration
  repeat while (current date) is less than endTime
    tell AppleScript to delay endTime - (current date)
  end repeat
end delay

This enables you to leave the rest of your script unchanged and you can use "delay" normally, e.g.,

delay 5
display alert "I like cake!"

[NOTE: Normally, the custom handler would use "continue delay duration" to invoke the built-in "delay", but I found that, although this works within Script Editor, it returns an error when used within an applet (“Can’t continue delay. (-1708)”). I worked around that issue by directly telling AppleScript to handle the delay command instead of using "continue" to get there.]

The issue is that delay processes user input while pausing the script, so you can still click on menus or windows displayed by an applet, and there is a bug (fixed in 10.11) where user input causes delay to not wait the full duration before resuming script execution. If you don't interact with the applet, delay works correctly.