Команда «затримка» AppleScript не працює з моменту переходу на Yosemite


10

Примітка . Проблема з delayвиправлена ​​в OS X 10.11 El Capitan.

З моменту переходу на Yosemite, Applescripts, які використовують затримки, перестали працювати. Як я можу це виправити?

Ось найпростіший у світі Applescript заради простого прикладу:

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

На це знадобиться 30 секунд. Якщо я запускаю його в редакторі сценаріїв (раніше редактор Applescript), на це потрібно 30 секунд. Але якщо я збережу цей скрипт як додаток, тоді, коли я запускаю програму, затримки ігноруються, і на додаток потрібно частку секунди.

Як змусити Applescript затриматись на певний час, перш ніж перейти до наступного кроку? Це глюк Yosemite? Чи є надійне рішення?


Це працює так, як очікувалося на моєму Mac (10.10.1)
markhunte

Будь-яка ідея, що змушує її не працювати на моїх? Для уточнення: він працює в редакторі сценаріїв, але якщо я збережу сценарій як додаток, а потім запустить додаток, затримки ігноруються. Це найдивніше.
2х1

У мене така ж проблема 10.10.3
Томас Темпельман

Повідомлено в Apple: openradar.me/21588747
Thomas Tempelmann

1
Ця проблема була виправлена ​​в OS X 10.11 El Capitan.
Кріс Пейдж

Відповіді:


7

Примітка . Проблема з delayвиправлена ​​в OS X 10.11 El Capitan.

@ 2oh1, ви маєте правильну основну думку у своїй відповіді, але ось повна і правильна відповідь:

Єдиний розумний спосіб подолати це - викликати "затримку" в циклі, що забезпечує бажану тривалість, перш ніж продовжувати. Найкращий спосіб зробити це - замінити "затримку" за допомогою спеціального обробника:

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

Це дозволяє залишити решту сценарію незмінною, і ви можете використовувати "затримку" нормально, наприклад,

delay 5
display alert "I like cake!"

[ПРИМІТКА: Зазвичай користувальницький обробник використовує "продовжити тривалість затримки", щоб викликати вбудовану "затримку", але я виявив, що, хоча це працює в редакторі сценаріїв, він повертає помилку, коли використовується в аплеті ("Можна" t продовжуйте затримку. (-1708) ”). Я вирішив цю проблему, прямо сказавши AppleScript обробляти команду затримки, а не використовувати "продовжити", щоб дістатися туди.]

Проблема полягає в тому, що delayобробляє введення користувача під час паузи сценарію, тож ви все одно можете натискати на меню чи вікна, відображені аплетом, і є помилка (зафіксовано в 10.11), коли введення користувача змушує delayне чекати повну тривалість до відновлення виконання сценарію. . Якщо ви не взаємодієте з аплетом, delayпрацює правильно.


Чи все це помилка, чи є причина затримки, що працює таким чином з Yosemite?
2oh1

Це помилка, яка затримка не затримується.
Кріс Пейдж

Це так дивно. Я розмовляв з яблучним сценарієм, який використовує затримку на іншу ніч, і раптом затримка знову нормально функціонувала. Я припускав, що помилка була виправлена. Через годину, хоч нічого не змінилося, помилка повернулася. Я справді збентежений. Це не має значення. Я використовую змінну для встановлення часу і затримки до п'яти хвилин пізніше (наприклад), і вона працює бездоганно. Отже ... проблема вирішена, але це не пояснює, чому проблема існує. Цікаво, цікаво, цікаво.
2oh1

1
Тому що Apple goofed. Програмне забезпечення Apple набагато менш надійне, оскільки вони почали випускати OS X щорічно. Мені не вистачає вищих версій ОС X (на зразок 10.6.8), де ОС була непомітна. Ви просто більше не отримуєте такого досвіду.
Вільям Т Фроггард

Якщо це помилка (з якою я згоден), чому я все ще не виправлена, мені цікаво. Хтось тут робив радарний звіт? Чи можете ви потім опублікувати його ідентифікатор? (або / також допис на openradar.me)
Томас Темпельман

5

Під час боротьби з цією ж проблемою я натрапив на цю відповідь на не дуже пов’язане з цим питання і вирішив спробувати його, і, здається, це працює для мене.

Просто замініть delay 5з do shell script "/bin/sleep 5"і отримати той же результат.


Дякую, що поділились! Як я вже говорив вище, я не в змозі перевірити це, тому що з причин, які для мене не мають сенсу, затримка 5 працює так, як і для мене зараз (я миттєво її перевірив ще раз). Я поняття не маю, чому це іноді працює, а іноді і не вдається. Це так дивно. Я в кінцевому підсумку використовую вирішення, де я отримую поточний час і встановлюю його як змінну, а потім призупиняю сценарій, доки час не буде змінним плюс одна хвилина (очевидно, на 1 хвилину затримки). Це незграбно, але він працює бездоганно місяцями, тоді як проста затримка була періодичною. Тьфу.
2oh1

Я працюю 10.10.5, і це рішення не працює, а також блокує сценарій на час сну
Грег

@Greg: Якщо він "блокує сценарій" на час сну, то він працює. /bin/sleepчекає тривалості сну і не повертається до його завершення. На відміну від цього, вбудована delayкоманда AppleScript обробляє події введення користувача під час паузи. (Де саме тут лежить помилка: якщо є введення з клавіатури користувача, delayпродовжується виконання сценарію до завершення тривалості затримки.)
Кріс Сторінка

3

Я не кажу, що це найкраще рішення, але, здається, воно вирішило мою проблему. Замість того, щоб використовувати просту затримку, яку ігнорують з незрозумілих мені причин, я перейшов до отримання часу та циклічного циклу до досягнення нового часу (він все ще використовує затримку, але не має значення, якщо вона ігнорується затримка, оскільки сценарій не триває до досягнення часу).

# 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

Я все ще вмираю, щоб знати, чому затримку ігнорують (або кардинально прискорили?! ??), але це робить роботу, незграбну, як це є.


Команда "затримка" не "скорочується", вона переривається. Затримуючи, він сидить у циклі, перевіряючи, чи є якісь події введення клавіатури, щоб він міг перевірити наявність Command-Period. Мабуть, це неправильно виходить із циклу затримки, коли виявляється будь-який ввід користувача.
Кріс Пейдж

Цікаво! Я виявляю, що його ігнорують (прискорили? Перервали?), Навіть коли мій Mac сидить у режимі очікування, але я не знаю, чому.
2oh1

Після того, як подія введення користувача знаходиться у черзі подій, delayвона буде продовжувати перериватися, поки щось не обробляє події та не видаляє їх з черги.
Кріс Пейдж

2

Я знайшов обхід у німецькому дописі на форумі . Додайте ці рядки до початку сценарію:

use framework "Foundation"
use scripting additions
current application's NSThread's sleepForTimeInterval:1

У мене виникають проблеми з тестуванням вашої відповіді, оскільки з будь-якої причини затримка зараз працює так, як очікувалося на моєму Mac. Я поняття не маю, чому. Я бігаю 10.10.3. Можливо, Apple виправила цю помилку? Або, можливо, це просто переривчаста проблема, яка наразі не впливає на мій Mac. Тьфу. Як я вже говорив вище, хоч у моєму вирішенні проблема полягає в тому, щоб Applescript отримати поточний час, а потім затримати до поточного часу плюс x.
2х1

Я також запускаю 10.10.3, і все ще не бачу проблеми. Оскільки далеко не всі бачать проблему, вона, ймовірно, переривається або пов'язана з програмним забезпеченням сторонніх виробників або з певними налаштуваннями налаштувань. Хто знає. До речі, ваш обхід, мабуть, є недоліком у тому, що додаток продовжує використовувати 100% часу процесора під час очікування, тоді як правильна поведінка затримки полягає у тому, щоб застосувати додаток до сну на той час, тим самим використовуючи менше енергії.
Томас Темпельман

Я працюю 10.10.5 і це рішення не працює.
Грег

@ThomasTempelmann: Проблема виникає, коли є введення користувача. Якщо ви не натискаєте або вводите під час запуску сценарію, помилка не спрацьовує.
Кріс Пейдж

Зауважте, що це рішення призводить до того, що програма фактично замерзає на час сну. delayобробляє введення користувача під час призупинення сценарію, тому ви все ще можете взаємодіяти з меню та вікнами, наприклад.
Кріс Пейдж

0

carzyj мав те, що я вважаю найкращою відповіддю, але в поєднанні з методом Кріса Пейджа ви отримуєте:

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

Ви можете прокоментувати "затримку" через "кінець затримки", щоб повернутися до початкової затримки.


Я також зробив подібну модифікацію коду, перш ніж побачити це. Я працюю 10.10.5, і це рішення не працює, а також блокує сценарій на час сну.
Грег

0

це модифікація рішення на сторінці @ chris

Здається, це баланс між чуйністю та точною фіксацією затримки.

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

Але замість того, щоб сказати Applescript затримати загальну тривалість, ми просто скажемо йому затриматись на дробовий період тривалості. якщо період менший, ніж дозволяє яблуко (1/60 секунди), то давайте просто встановимо його на цю дельту. Що ми можемо зберігати деяку чуйність, але все одно залишаємось точними. підозра в тому, що іноді затримка не працює, тому повтор, поки цикл буде тримати заблоковану нитку, але в сценаріях успіху ми хочемо, щоб дельта затримки була короткою, щоб процес все-таки був перерваний


Скорочення запитуваної затримки є непотрібним і може лише зробити сценарій повільнішим і споживати більше процесора під час очікування. Моя версія просто викликає затримку, поки не закінчиться потрібна тривалість, що дозволяє delayзатримати стільки, скільки може, до того, як вона продовжить виконання.
Кріс Пейдж

Зауважте, що оскільки ця відповідь була опублікована, я оновив свій код, щоб використовувати delay endTime - (current date)замість цього delay duration, що гарантує, що якщо delay не буде перервано, він не призупинить сценарій довше, ніж спочатку запитували час, який, можливо, ви намагалися адресу з цією відповіддю.
Кріс Пейдж

0

Таким чином, я вважаю, що Кріс це означає:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.