El comando “retraso” de AppleScript no funciona desde que se cambió a Yosemite

10

Nota: El problema con delay se solucionó en OS X 10.11 El Capitan.

Desde que me actualicé a Yosemite, Applescripts que usan retrasos han dejado de funcionar. ¿Cómo puedo solucionar esto?

Este es el ejemplo más simple del mundo, por un simple ejemplo:

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

Eso debería tardar 30 segundos en completarse. Si lo ejecuto en el Editor de secuencias de comandos (anteriormente Editor de Apple), tarda 30 segundos en completarse. Pero si guardo este script como una aplicación, cuando lanzo la aplicación, los retrasos se ignoran y la aplicación tarda una fracción de segundo en completarse.

¿Cómo puedo forzar a Applescript a que se retrase por un tiempo específico antes de pasar al siguiente paso? ¿Es este un fallo de Yosemite? ¿Hay una solución confiable?

    
pregunta 2oh1 14.12.2014 - 00:21

7 respuestas

7

Nota: El problema con delay se solucionó en OS X 10.11 El Capitan.

@ 2oh1, tienes la idea básica correcta en tu respuesta, pero aquí hay una respuesta completa y correcta:

La única forma razonable de solucionar esto es invocar "retardo" dentro de un bucle que garantice que transcurre la duración deseada antes de continuar. La mejor manera de hacerlo es anular el "retraso" con un controlador personalizado:

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

Esto te permite dejar el resto de la secuencia de comandos sin cambios y puedes usar el "retraso" normalmente, por ejemplo,

delay 5
display alert "I like cake!"

[NOTA: Normalmente, el controlador personalizado usaría "continuar con la duración del retardo" para invocar el "retardo" incorporado, pero descubrí que, aunque esto funciona en el Editor de secuencias de comandos, devuelve un error cuando se usa dentro de un applet ( "No se puede continuar el retraso. (-1708)"). Resolví ese problema diciéndole directamente a AppleScript que manejara el comando de demora en lugar de usar "continuar" para llegar allí.]

El problema es que delay procesa la entrada del usuario al pausar la secuencia de comandos, por lo que aún puede hacer clic en los menús o ventanas que muestra un applet, y hay un error (corregido en 10.11) donde la entrada del usuario hace que delay No espere la duración completa antes de reanudar la ejecución del script. Si no interactúas con el applet, delay funciona correctamente.

    
respondido por el Chris Page 25.02.2015 - 07:47
5

Mientras luchaba contra este mismo problema, encontré esta respuesta con un pregunta no tan relacionada y decidí probarlo y parece funcionar para mí.

Simplemente reemplaza delay 5 con do shell script "/bin/sleep 5" y obtén el mismo resultado.

    
respondido por el JCobb 27.07.2015 - 23:39
3

No estoy diciendo que esta sea la mejor solución, pero parece haber resuelto mi problema. En lugar de utilizar un retardo simple, que se ignora por razones que no entiendo, he cambiado a obtener el tiempo y el bucle hasta que se alcanza un nuevo tiempo (todavía se usa un retardo, pero no importa si se ignora). la demora desde que el script no continúa hasta que se alcanza el tiempo).

# 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

Todavía me muero por saber por qué se ignora la demora (o ¿¿se ha acelerado drásticamente?! ??), pero esto hace el trabajo, por torpe que sea.

    
respondido por el 2oh1 14.12.2014 - 03:24
2

Encontré una solución alternativa en un mensaje del foro en alemán . Agregue estas líneas en la parte superior de su script:

use framework "Foundation"
use scripting additions
current application's NSThread's sleepForTimeInterval:1
    
respondido por el Thomas Tempelmann 29.06.2015 - 12:09
0

carzyj tuvo lo que considero la mejor respuesta, pero cuando se combina con el método de Chris Page, obtienes:

on delay duration
  do shell script "/bin/sleep " & duration
end delay

Puedes comentar "en demora" hasta "demora final" para volver a la demora original.

    
respondido por el Dickster 20.09.2015 - 17:19
0

esta es una modificación de la solución @ chris-page

Parece ser un equilibrio entre la capacidad de respuesta y la captura precisa del retraso.

on delay duration
    set endTime to (current date) + duration
    repeat while (current date) is less than endTime
        set delta to duration / 100
        if duration < 0.2 then
            set delta to 0.2
        end if
        tell AppleScript to delay delta
    end repeat
end delay

Pero en lugar de decirle a Applescript que demore la duración total, simplemente le decimos que demore por un período fraccionario de la duración. si el período es menor al que permite la manzana (1/60 de segundo), entonces simplemente configurémoslo en ese delta. Que podamos mantener cierta capacidad de respuesta, y aun así ser precisos. la sospecha es que a veces el retraso no funciona, por lo tanto, el ciclo de repetición mientras mantiene el hilo bloqueado, pero en los escenarios de éxito, queremos que el retraso delta sea corto para que el proceso aún pueda ser interrumpido

    
respondido por el Greg 08.12.2015 - 09:02
0

Entonces, para ponerlo todo junto, creo que Chris significa esto:

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
    
respondido por el Dick.Guertin 09.12.2015 - 17:40

Lea otras preguntas en las etiquetas