AppleScript “delay” command not working since switch to Yosemite
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.
While battling this same problem I came across this answer to a not-so-related question and decided to try it and it seems to work for me.
Replace delay 5
with do shell script "/bin/sleep 5"
and get the same result.
I'm not saying this is the best solution, but it seems to have solved my problem. Instead of using a simple delay, which is being ignored for reasons I do not understand, I've switched to getting the time and looping until a new time is reached (it still uses a delay, but it doesn't matter if it ignores the delay since the script doesn't continue until the time is reached).
# Pause for five minutes
set GetTheTime to current date
set NewTime to GetTheTime + (5 * minutes)
repeat while (current date) is less than NewTime
delay 60
end repeat
I'm still dying to know why delay is being ignored (or dramatically sped up?!??), but this gets the job done, clumsy as it is.