Perintah “penundaan” AppleScript tidak berfungsi sejak beralih ke Yosemite

10

Catatan: Masalah dengan delaytelah diperbaiki di OS X 10.11 El Capitan.

Sejak saya memutakhirkan ke Yosemite, Applescripts yang menggunakan penundaan telah berhenti berfungsi. Bagaimana saya bisa memperbaikinya?

Inilah Applescript paling sederhana di dunia, untuk contoh yang mudah:

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

Itu harus memakan waktu 30 detik untuk selesai. Jika saya menjalankannya di Script Editor (sebelumnya Applescript Editor) dibutuhkan 30 detik untuk menyelesaikannya. Tetapi jika saya menyimpan skrip ini sebagai aplikasi, ketika saya meluncurkan aplikasi, penundaan diabaikan dan aplikasi membutuhkan waktu sepersekian detik untuk menyelesaikannya.

Bagaimana saya bisa memaksa Applescript untuk menunda waktu tertentu sebelum melanjutkan ke langkah berikutnya? Apakah ini kesalahan Yosemite? Apakah ada solusi yang dapat diandalkan?

2oh1
sumber
Ini berfungsi seperti yang diharapkan pada Mac saya (10.10.1)
markhunte
Adakah yang tahu mengapa itu tidak berhasil pada saya? Untuk memperjelas: ini berfungsi di Script Editor, tetapi jika saya menyimpan skrip sebagai aplikasi dan kemudian meluncurkan aplikasi, penundaan diabaikan. Itu hal yang paling aneh.
2oh1
Saya memiliki masalah yang sama pada 10.10.3
Thomas Tempelmann
Dilaporkan ke Apple: openradar.me/21588747
Thomas Tempelmann
1
Masalah ini diperbaiki pada OS X 10.11 El Capitan.
Chris Page

Jawaban:

7

Catatan: Masalah dengan delaytelah diperbaiki di OS X 10.11 El Capitan.

@ 2oh1, Anda memiliki ide dasar yang tepat dalam jawaban Anda, tetapi inilah jawaban yang lengkap dan benar:

Satu-satunya cara yang masuk akal untuk mengatasi ini adalah dengan memanggil "penundaan" dalam satu lingkaran yang memastikan durasi yang diinginkan berlalu sebelum melanjutkan. Cara terbaik untuk melakukannya adalah mengganti "tunda" dengan penangan khusus:

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

Ini memungkinkan Anda untuk membiarkan sisa skrip Anda tidak berubah dan Anda dapat menggunakan "penundaan" secara normal, misalnya,

delay 5
display alert "I like cake!"

[CATATAN: Biasanya, penangan kustom akan menggunakan "lanjutkan durasi penundaan" untuk memanggil "penundaan" bawaan, tetapi saya menemukan bahwa, meskipun ini berfungsi di dalam Script Editor, ia mengembalikan kesalahan ketika digunakan dalam applet ("Can ' t lanjutkan penundaan. (-1708) ”). Saya mengatasi masalah itu dengan secara langsung memberitahu AppleScript untuk menangani perintah penundaan alih-alih menggunakan "lanjutkan" untuk sampai ke sana.]

Masalahnya adalah bahwa delayproses input pengguna saat menjeda skrip, sehingga Anda masih dapat mengklik menu atau jendela yang ditampilkan oleh applet, dan ada bug (diperbaiki pada 10.11) di mana input pengguna menyebabkan delaytidak menunggu durasi penuh sebelum melanjutkan eksekusi skrip . Jika Anda tidak berinteraksi dengan applet, delayberfungsi dengan benar.

Chris Page
sumber
Apakah semua ini bug, atau adakah alasan penundaan bekerja seperti ini dengan Yosemite?
2oh1
Ini adalah bug yang menunda tidak menunda.
Chris Halaman
Ini sangat aneh. Saya bermain-main dengan applescript yang menggunakan penundaan malam itu, dan tiba-tiba, penundaan berfungsi dengan benar lagi. Saya menduga bug telah diperbaiki. Satu jam kemudian, meskipun tidak ada yang berubah, bug itu kembali. Saya benar-benar bingung. Itu tidak masalah. Saya menggunakan variabel untuk mengatur waktu dan penundaan hingga lima menit kemudian (misalnya), dan itu berfungsi dengan baik. Jadi ... masalah terpecahkan, tetapi itu tidak menjelaskan mengapa masalah itu ada. Menarik, menarik, menarik.
2oh1
1
Karena Apple melakukan kesalahan. Perangkat lunak Apple jauh kurang dapat diandalkan karena mereka mulai merilis OS X setiap tahun. Saya kehilangan OS X versi minor yang lebih tinggi (seperti 10.6.8) di mana OS-nya sangat solid. Anda hanya tidak mendapatkan pengalaman seperti itu lagi.
William T Froggard
Jika itu bug (yang saya setujui), mengapa ini tidak diperbaiki, saya bertanya-tanya. Adakah yang membuat laporan radar di sini? Apakah Anda kemudian memposting ID-nya? (atau / juga posting di openradar.me)
Thomas Tempelmann
5

Sambil berjuang menghadapi masalah yang sama ini, saya menemukan jawaban untuk pertanyaan yang tidak begitu terkait ini dan memutuskan untuk mencobanya dan tampaknya berhasil bagi saya.

Cukup ganti delay 5dengan do shell script "/bin/sleep 5"dan dapatkan hasil yang sama.

JCobb
sumber
Terima kasih telah berbagi! Seperti yang saya katakan sebelumnya di atas, saya tidak dapat menguji ini karena, untuk alasan yang tidak masuk akal bagi saya, penundaan 5 berfungsi sebagaimana mestinya bagi saya sekarang (saya baru saja mengujinya lagi beberapa saat yang lalu). Saya tidak tahu mengapa ini kadang-kadang berhasil dan kadang gagal. Ini sangat aneh. Saya akhirnya menggunakan solusi di mana saya mendapatkan waktu saat ini dan mengaturnya sebagai variabel, dan kemudian menjeda skrip sampai waktunya variabel ditambah satu menit (untuk penundaan 1 menit, jelas). Itu kikuk, tetapi bekerja dengan sempurna selama berbulan-bulan, sedangkan penundaan sederhana telah terputus-putus. Ugh.
2oh1
Saya menjalankan 10.10.5 dan solusi ini tidak bekerja dan juga mengunci skrip selama durasi tidur
Greg
@Reg: Jika "mengunci skrip" untuk durasi tidur, maka itu berfungsi. /bin/sleepmenunggu durasi tidur dan tidak kembali sampai selesai. Sebaliknya, delayperintah bawaan AppleScript menangani peristiwa input pengguna saat skrip dijeda. (Di situlah letak bug: jika ada input keyboard pengguna, delaylanjutkan eksekusi skrip sebelum durasi penundaan selesai.)
Chris Page
3

Saya tidak mengatakan ini adalah solusi terbaik, tetapi tampaknya telah menyelesaikan masalah saya. Alih-alih menggunakan penundaan sederhana, yang diabaikan karena alasan yang saya tidak mengerti, saya telah beralih untuk mendapatkan waktu dan perulangan sampai waktu baru tercapai (masih menggunakan penundaan, tetapi tidak masalah jika diabaikan penundaan karena skrip tidak berlanjut sampai waktu tercapai).

# 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

Saya masih ingin tahu mengapa penundaan diabaikan (atau dipercepat secara dramatis?! ??), tetapi ini menyelesaikan pekerjaan, kikuk seperti itu.

2oh1
sumber
Perintah "delay" tidak sedang "dipercepat", sedang diinterupsi. Sementara menunda, ia duduk dalam satu lingkaran memeriksa apakah ada peristiwa input keyboard sehingga dapat memeriksa Periode-Perintah. Tampaknya itu salah keluar dari loop tunda ketika input pengguna terdeteksi.
Chris Page
Menarik! Saya menemukan bahwa itu diabaikan (dipercepat? Terganggu?) Bahkan ketika Mac saya duduk diam, tetapi saya tidak tahu mengapa.
2oh1
Setelah peristiwa input pengguna dalam antrian acara, delayakan terus terputus hingga ada yang menangani acara dan menghapusnya dari antrian.
Chris Page
2

Saya menemukan solusi di pos forum Jerman . Tambahkan baris ini ke bagian atas skrip Anda:

use framework "Foundation"
use scripting additions
current application's NSThread's sleepForTimeInterval:1
Thomas Tempelmann
sumber
Saya mengalami masalah dalam menguji jawaban Anda karena, untuk alasan apa pun, penundaan saat ini berfungsi seperti yang diharapkan pada Mac saya. Saya tidak tahu kenapa. Saya menjalankan 10.10.3. Mungkin Apple memperbaiki bug ini? Atau, mungkin itu hanya masalah intermiten yang tidak memengaruhi Mac saya saat ini. Ugh. Seperti yang saya katakan di atas, solusi saya adalah membuat Applescript mendapatkan waktu sekarang dan kemudian menunda sampai waktu sekarang ditambah x.
2oh1
Saya menjalankan 10.10.3 juga dan masih melihat masalah. Karena tidak semua orang melihat masalah, itu mungkin terputus-putus atau terkait dengan perangkat lunak pihak ketiga atau pengaturan preferensi tertentu. Siapa tahu. BTW, pekerjaan Anda di sekitar mungkin memiliki kelemahan bahwa aplikasi terus menggunakan waktu CPU 100% saat menunggu, sedangkan perilaku penundaan yang tepat adalah menempatkan aplikasi untuk tidur selama durasi itu, sehingga menggunakan daya yang lebih kecil.
Thomas Tempelmann
Saya menjalankan 10.10.5 dan solusi ini tidak berfungsi.
Greg
@ThomasTempelmann: Masalah terjadi ketika ada input pengguna. Jika Anda tidak mengklik atau mengetik saat skrip berjalan, bug tidak terpicu.
Chris Page
Perhatikan bahwa solusi ini menyebabkan aplikasi benar-benar membeku selama tidur. delaymemproses input pengguna saat skrip dijeda, jadi Anda masih dapat berinteraksi dengan menu dan jendela, misalnya.
Chris Page
0

carzyj memiliki apa yang saya anggap sebagai jawaban terbaik, tetapi ketika dikombinasikan dengan metode Chris Page, Anda mendapatkan:

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

Anda dapat mengomentari "penundaan" melalui "tunda akhir" untuk kembali ke penundaan awal.

Dickster
sumber
Saya juga membuat modifikasi kode yang serupa, sebelum melihat ini. Saya menjalankan 10.10.5 dan solusi ini tidak berfungsi dan juga mengunci skrip selama durasi tidur.
Greg
0

ini adalah modifikasi dari solusi @ chris-page

Tampaknya menjadi keseimbangan antara responsif dan secara akurat menangkap penundaan.

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

Tetapi alih-alih mengatakan pada Applescript untuk menunda durasi keseluruhan, kami hanya mengatakannya untuk menunda untuk periode fraksional durasi. jika periode kurang dari yang diizinkan apel (1/60 detik), maka mari kita atur ke delta itu. Bahwa kita dapat menjaga respons, namun tetap akurat. kecurigaannya adalah bahwa kadang-kadang keterlambatan tidak bekerja sehingga pengulangan sementara loop akan membuat utas tetap terkunci, tetapi dalam skenario sukses, kami ingin penundaan delta menjadi singkat sehingga proses masih dapat terganggu

Greg
sumber
Memperpendek penundaan yang diminta tidak perlu dan hanya dapat membuat skrip berjalan lebih lambat dan mengkonsumsi lebih banyak CPU sambil menunggu. Versi saya hanya memanggil penundaan sampai seluruh durasi yang diinginkan telah berlalu, memungkinkan delayuntuk menunda sebanyak mungkin sebelum melanjutkan eksekusi.
Chris Page
Perhatikan bahwa karena jawaban ini diposkan, saya memperbarui kode saya untuk digunakan delay endTime - (current date)sebagai gantinya delay duration, yang memastikan bahwa jika delay tidak terganggu tidak akan menghentikan skrip lebih lama dari waktu yang diminta semula, yang mungkin merupakan apa yang Anda coba alamat dengan jawaban ini.
Chris Page
0

Jadi, untuk menyatukan semuanya, saya percaya Chris berarti ini:

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
Dick. Guertin
sumber