Il comando "delay" di AppleScript non funziona da quando si passa a Yosemite

10

Nota: il problema con delay è stato risolto in OS X 10.11 El Capitan.

Da quando ho eseguito l'upgrade a Yosemite, gli Applescript che utilizzano i ritardi hanno smesso di funzionare. Come posso risolvere questo problema?

Ecco l'Applescript più semplice del mondo, per un semplice esempio:

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

Questo dovrebbe richiedere 30 secondi per essere completato. Se lo eseguo in Script Editor (precedentemente Applescript Editor) ci vogliono 30 secondi per essere completato. Ma se salvo questo script come app, quando lancio l'app, i ritardi vengono ignorati e l'app richiede una frazione di secondo per essere completata.

Come posso costringere Applescript a ritardare per un periodo di tempo specificato prima di passare al passaggio successivo? Questo è un problema tecnico di Yosemite? C'è una soluzione affidabile?

    
posta 2oh1 14.12.2014 - 00:21
fonte

7 risposte

7

Nota: il problema con delay è stato risolto in OS X 10.11 El Capitan.

@ 2oh1, hai la giusta idea di base nella tua risposta, ma ecco una risposta completa e corretta:

L'unico modo ragionevole per ovviare a questo è di invocare il "ritardo" all'interno di un ciclo che garantisce la durata desiderata prima di continuare. Il modo migliore per farlo è sostituire il "ritardo" con un gestore personalizzato:

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

Ciò ti consente di lasciare invariato il resto dello script e di utilizzare normalmente "delay", ad es.

delay 5
display alert "I like cake!"

[NOTA: Normalmente, il gestore personalizzato usa "continue delay duration" per invocare il "ritardo" incorporato, ma ho scoperto che, sebbene funzioni all'interno di Script Editor, restituisce un errore quando viene utilizzato all'interno di un'applet ( "Impossibile continuare il ritardo. (-1708)"). Ho risolto il problema dicendo direttamente a AppleScript di gestire il comando delay anziché utilizzare "continue" per arrivarci.]

Il problema è che delay elabora l'input dell'utente mentre mette in pausa lo script, quindi puoi ancora fare clic sui menu o le finestre visualizzati da un'applet, e c'è un bug (corretto in 10.11) dove l'input dell'utente causa delay a non aspettare tutta la durata prima di riprendere l'esecuzione dello script. Se non interagisci con l'applet, delay funziona correttamente.

    
risposta data 25.02.2015 - 07:47
fonte
5

Mentre combattevo questo stesso problema mi sono imbattuto in questa risposta a un domanda non correlata e ho deciso di provarlo e sembra funzionare per me.

Sostituisci semplicemente delay 5 con do shell script "/bin/sleep 5" e ottieni lo stesso risultato.

    
risposta data 27.07.2015 - 23:39
fonte
3

Non sto dicendo che questa sia la soluzione migliore, ma sembra aver risolto il mio problema. Invece di usare un semplice ritardo, che viene ignorato per ragioni che non capisco, sono passato a ottenere il tempo e il ciclo fino a quando non è stato raggiunto un nuovo tempo (utilizza ancora un ritardo, ma non importa se ignora il ritardo poiché lo script non continua fino al raggiungimento del tempo).

# 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

Sto ancora morendo dalla voglia di sapere perché il ritardo viene ignorato (o drammaticamente accelerato?! ??), ma questo ha portato a termine il lavoro, per quanto sia goffo.

    
risposta data 14.12.2014 - 03:24
fonte
2

Ho trovato un work-around in un tedesco post sul forum . Aggiungi queste righe all'inizio dello script:

use framework "Foundation"
use scripting additions
current application's NSThread's sleepForTimeInterval:1
    
risposta data 29.06.2015 - 12:09
fonte
0

carzyj ha quello che considero la risposta migliore, ma quando combinato con il metodo di Chris Page, ottieni:

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

Puoi commentare "in ritardo" con "fine ritardo" per ripristinare il ritardo originale.

    
risposta data 20.09.2015 - 17:19
fonte
0

questa è una modifica alla soluzione @ chris-page

Sembra essere un equilibrio tra la reattività e la cattura accurata del ritardo.

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

Ma invece di dire a Applescript di posticipare per la durata complessiva, ci limitiamo a posticipare per un periodo frazionario della durata. se il periodo è inferiore a quello consentito da Apple (1/60 di secondo), impostalo su quel delta. Che possiamo mantenere un po 'di reattività, ma essere comunque precisi. il sospetto è che a volte il ritardo non funzioni in modo che il ciclo di ripetizione continui a mantenere il thread bloccato, ma in scenari di successo, vogliamo che il ritardo delta sia breve, in modo che il processo possa ancora essere interrotto

    
risposta data 08.12.2015 - 09:02
fonte
0

Quindi, per mettere tutto insieme, credo che Chris intenda questo:

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
    
risposta data 09.12.2015 - 17:40
fonte

Leggi altre domande sui tag