Uwaga: Problem z delay
został rozwiązany w OS X 10.11 El Capitan.
Odkąd zaktualizowałem do Yosemite, Applescripts używające opóźnień przestały działać . Jak mogę to naprawić?
Oto najprostszy skrypt Applescript na świecie, dla prostego przykładu:
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
Powinno to zająć 30 sekund. Jeśli uruchomię go w edytorze skryptów (dawniej Applescript Editor), ukończenie zajmie 30 sekund. Ale jeśli zapiszę ten skrypt jako aplikację, po uruchomieniu aplikacji opóźnienia są ignorowane, a aplikacja zajmuje ułamek sekundy.
Jak mogę zmusić Applescript do opóźnienia o określoną kwotę czasu przed przejściem do następnego kroku? Czy to usterka Yosemite? Czy istnieje niezawodne obejście?
Komentarze
- Działa to zgodnie z oczekiwaniami na moim Macu (10.10.1)
- Każdy pomysł co powoduje, że nie działa na moim? Dla wyjaśnienia: działa w Edytorze skryptów, ale jeśli zapiszę skrypt jako aplikację, a następnie uruchomię aplikację, opóźnienia są ignorowane. To ' to najdziwniejsza rzecz.
- Mam ten sam problem w wersji 10.10.3
- Zgłoszone do Apple: openradar.me/21588747
- Ten problem został rozwiązany w systemie OS X 10.11 El Capitan.
Odpowiedź
Uwaga: Problem z delay
został poprawiony w OS X 10.11 El Capitan.
@ 2oh1, masz w swojej odpowiedzi właściwy podstawowy pomysł, ale oto pełna i poprawna odpowiedź:
Jedynym rozsądnym sposobem obejścia tego jest wywołanie „opóźnienia” w pętli, która zapewnia, że upłynie żądany czas trwania przed kontynuowaniem. Najlepszym sposobem na to jest zastąpienie „opóźnienia” niestandardową procedurą obsługi:
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
Dzięki temu możesz pozostawić resztę skryptu niezmienioną i możesz normalnie używać opcji „delay”, np.
delay 5 display alert "I like cake!"
[UWAGA: Normalnie, niestandardowy program obsługi używałby „czasu trwania kontynuacji opóźnienia” do wywołania wbudowane „opóźnienie”, ale stwierdziłem, że chociaż działa to w edytorze skryptów, zwraca błąd, gdy jest używane w aplecie („Nie można kontynuować opóźnienia. (-1708) ”). Obejrzałem ten problem, mówiąc bezpośrednio AppleScript, aby obsłużył polecenie opóźnienia zamiast używania „continue”, aby się tam dostać.]
Problem polega na tym, że delay
przetwarza użytkownika wprowadzanie danych podczas wstrzymywania skryptu, dzięki czemu nadal można klikać menu lub okna wyświetlane przez aplet, i jest błąd (naprawiony w 10.11), w którym dane wejściowe użytkownika powodują, że delay
nie czeka na cały czas przed wznowieniem wykonywania skryptu. Jeśli nie wchodzisz w interakcję z apletem, delay
działa poprawnie.
Komentarze
- To wszystko z tego jest błędem, czy też istnieje powód, dla którego opóźnienie działa w ten sposób w Yosemite?
- To błąd, który powoduje, że opóźnienie nie jest ' t opóźnieniem.
- To ' jest takie dziwne. Majstrowałem przy skrypcie jabłkowym, który używa opóźnienia drugiej nocy i nagle opóźnienie znów działa poprawnie. Zakładałem, że błąd został naprawiony . Godzinę później, mimo że nic się nie zmieniło, błąd powrócił. Jestem ' naprawdę zbity z tropu. Nie ' nie ma to jednak znaczenia . ' używam zmiennej do ustawiania czasu i opóźnienia do pięciu minut później (na przykład) i ' działa idealnie . Więc … problem rozwiązany, ale to nie ' nie wyjaśnia, dlaczego problem istnieje. Ciekawe, interesujące, interesujące.
- Ponieważ Apple pomyliło się. oprogramowanie jest znacznie mniej niezawodne, odkąd zaczęto wydawać OS X co roku. Brakuje mi wyższych wersji pomocniczych OS X (takich jak 10.6.8), w których system operacyjny był solidny. Po prostu nie ' nie masz już takiego doświadczenia.
- Jeśli ' jest błędem (zgadzam się z), dlaczego nie ' t nadal nie jest to naprawione, zastanawiam się. Czy ktoś tutaj sporządził raport z radaru? Czy mógłbyś więc zamieścić jego identyfikator? (lub / także opublikuj na openradar.me)
Odpowiedź
Walcząc z tym samym problemem, na który natknąłem się tę odpowiedź na pytanie niezbyt związane i zdecydowałem się go wypróbować i wygląda na to, że działa dla mnie.
Zamień delay 5
na do shell script "/bin/sleep 5"
i uzyskaj ten sam wynik.
Komentarze
- Dziękujemy za udostępnienie! Jak powiedziałem wcześniej, ' nie mogę tego przetestować, ponieważ z powodów, które nie mają dla mnie sensu, opóźnienie 5 działa teraz tak, jak powinno (właśnie przetestowałem to znowu przed chwilą). Nie mam pojęcia, dlaczego to czasami działa, a czasami zawodzi.To ' jest takie dziwne. Skończyło się na zastosowaniu obejścia, w którym otrzymuję bieżący czas i ustawiam go jako zmienną, a następnie wstrzymuję skrypt, aż czas będzie zmienny plus jedna minuta (oczywiście z 1-minutowym opóźnieniem). ' jest niezgrabny, ale ' działał bezbłędnie przez wiele miesięcy, podczas gdy proste opóźnienie było sporadyczne. Ugh.
- Używam 10.10.5 i to rozwiązanie nie działa, a także blokuje skrypt na czas uśpienia.
- @Greg: Jeśli „blokuje skrypt” dla czas uśpienia, a następnie ' działa.
/bin/sleep
czeka na czas uśpienia i nie wraca, dopóki się nie zakończy. Z kolei polecenie AppleScript ' s wbudowanedelay
obsługuje zdarzenia wprowadzania danych przez użytkownika, gdy skrypt jest wstrzymany. (Na czym polega błąd: jeśli użytkownik wprowadza dane wejściowe z klawiatury,delay
kontynuuje wykonywanie skryptu przed upływem czasu opóźnienia).
Odpowiedź
Nie twierdzę, że to najlepsze rozwiązanie, ale wygląda na to, że rozwiązało mój problem. Zamiast używać prostego opóźnienia, które jest ignorowane z powodów, których nie rozumiem, przełączyłem się na pobieranie czasu i zapętlanie aż do osiągnięcia nowego czasu (nadal używa opóźnienia, ale nie ma znaczenia, czy ignoruje opóźnienie, ponieważ skrypt nie kontynuuje do czas został osiągnięty).
# 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
Wciąż nie mogę się doczekać, aby wiedzieć, dlaczego opóźnienie jest ignorowane (lub dramatycznie przyspieszane?! ??), ale praca wykonana, choć niezgrabna.
Komentarze
- ” opóźnienie ” polecenie nie ' nie jest ” przyspieszyło ” , to ' jest przerywany. Opóźniając, siedzi w pętli sprawdzając, czy są jakieś zdarzenia wejściowe z klawiatury, więc może sprawdzić czas polecenia. Najwyraźniej nieprawidłowo wychodzi z pętli opóźnienia po wykryciu jakichkolwiek danych wejściowych użytkownika.
- Interesujące! ' stwierdzam, że ' jest ignorowany (przyspieszany? Przerywany?), Nawet gdy mój Mac jest bezczynny, ale ja tego nie robię ' nie wiem dlaczego.
- Gdy zdarzenie wprowadzane przez użytkownika znajdzie się w kolejce zdarzeń,
delay
będzie kontynuowane być przerywane, dopóki coś nie obsłuży zdarzeń i nie usunie ich z kolejki.
Odpowiedź
Znalazłem pracę- w niemieckim poście na forum . Dodaj te wiersze na początku skryptu:
use framework "Foundation" use scripting additions current application"s NSThread"s sleepForTimeInterval:1
Komentarze
- I ' Mam problem z przetestowaniem Twojej odpowiedzi, ponieważ z jakiegoś powodu opóźnienie działa obecnie zgodnie z oczekiwaniami na moim Macu. Nie mam pojęcia dlaczego. Jestem ' korzystam z wersji 10.10.3. Być może Apple naprawiło ten błąd? A może to ' jest tylko sporadycznym problemem, który nie ' nie dotyczy mojego Maca w tej chwili. Fuj. Jak powiedziałem powyżej, moim obejściem jest to, że Applescript pobiera aktualny czas, a następnie opóźnia do aktualnego czasu plus x.
- Używam również wersji 10.10.3 i nadal widzę problem. Ponieważ nie każdy widzi ten problem, ' jest prawdopodobnie sporadyczny lub związany z oprogramowaniem innych firm lub z określonymi ustawieniami preferencji. Kto wie. Swoją drogą, twoje obejście ma prawdopodobnie tę wadę, że aplikacja zużywa 100% czasu procesora podczas oczekiwania, podczas gdy właściwym zachowaniem opóźnienia jest uśpienie aplikacji na ten czas, a tym samym zużycie energii.
- Używam wersji 10.10.5 i to rozwiązanie nie działa.
- @ThomasTempelmann: Problem występuje, gdy użytkownik wprowadza dane. Jeśli ' nie klikniesz ani nie wpiszesz w trakcie działania skryptu, błąd nie zostanie ' wywołany.
- Zauważ, że to rozwiązanie powoduje, że aplikacja faktycznie zawiesza się na czas snu.
delay
przetwarza dane wejściowe użytkownika podczas wstrzymania skryptu, więc możesz nadal korzystać z menu i okien, na przykład.
Odpowiedź
carzyj miał to, co uważam za najlepszą odpowiedź, ale w połączeniu z metodą Chrisa Pagea otrzymujesz:
on delay duration do shell script "/bin/sleep " & duration end delay
Możesz dodać komentarz „on delay” do „end delay”, aby powrócić do oryginalnego opóźnienia.
Komentarze
- I również dokonałem podobnej modyfikacji kodu, zanim to zobaczyłem. Używam 10.10.5 i to rozwiązanie nie działa, a także blokuje skrypt na czas uśpienia.
Odpowiedź
to jest modyfikacja rozwiązania @ chris-page
Wydaje się, że jest to równowaga między responsywnością a dokładnym uchwyceniem opóźnienia.
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
Ale zamiast nakazać Applescriptowi opóźnienie o cały czas trwania, po prostu mówimy mu, aby opóźnił się o ułamek czasu trwania. jeśli okres jest krótszy niż to, na co pozwala jabłko (1/60 sekundy), po prostu ustawmy go na tę deltę. Abyśmy mogli zachować pewną responsywność, ale nadal być dokładni. podejrzewa się, że czasami opóźnienie nie działa działa tak, aby pętla powtarzania while utrzymywała wątek w stanie zamkniętym, ale w scenariuszach sukcesu chcemy, aby delta opóźnienia była krótka, aby proces nadal mógł zostać przerwany.
Komentarze
- Skrócenie żądanego opóźnienia jest niepotrzebne i może jedynie spowolnić działanie skryptu i zużywać więcej procesora podczas oczekiwania. Moja wersja po prostu wywołuje opóźnienie do upływu całego żądanego czasu trwania, umożliwiając
delay
opóźnienie tak bardzo, jak to możliwe, zanim będzie kontynuowane. - Zauważ, że od tej odpowiedzi został opublikowany, zaktualizowałem kod tak, aby używał
delay endTime - (current date)
zamiastdelay duration
, co zapewnia, że jeślidelay
nie ' t zostanie przerwany, nie zostanie przerwany ' nie wstrzyma skryptu dłużej niż pierwotnie żądany czas , co mogło być tym, do czego próbujesz się odnieść za pomocą tej odpowiedzi.
Odpowiedź
Tak więc, aby umieścić to wszystko razem, myślę, że Chris ma to na myśli:
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