【问题标题】:Why is this AppleScript idle timer not triggering correctly?为什么这个 AppleScript 空闲计时器没有正确触发?
【发布时间】:2016-11-21 12:37:58
【问题描述】:

我正在尝试创建一个在特定时间递增的计时器(在这种情况下,只要时间是 xx:03:24)并在达到用户输入的值时发送通知。一旦这样做,它会重置增量并重复,直到手动退出。

但是,此代码无法在应有的触发时可靠地触发。有人猜到为什么吗?

on quit
    continue quit
end quit
tell application "Notifications Scripting"
    set event handlers script path to (path to me)
end tell

global actions, newActions

using terms from application "Notifications Scripting"
    on notification activated
        tell application "Safari"
            activate
            set winlist to every window
            repeat with win in winlist
                set numtabs to 0
                try
                    set tablist to every tab of win
                    set numtabs to length of tablist
                end try
                if numtabs is greater than 0 then
                    repeat with t in tablist

                        if "fallenlondon.storynexus.com" is in (URL of t as string) then
                            tell application "System Events"
                                tell window id (id of win as integer) of application "Safari" to set current tab to tab (index of t as integer)
                            end tell
                        end if
                    end repeat
                end if
            end repeat
        end tell
    end notification activated
end using terms from

display dialog "How many actions do you want to build up before being notified?" default answer "1"

set actions to (text returned of result) as number
set newActions to 0

on idle
    if ((seconds of (current date)) = 24) and ((minutes of (current date)) mod 10 = 3) then
        set newActions to (newActions + 1)
        set delayTime to 540
    else
        set delayTime to 0.5
    end if

    if newActions ≥ actions then
        if newActions = 1 then
            tell application "Notifications Scripting" to display notification "Fallen London" message "You have " & newActions & " new action!" sound name "Glass"
        else
            tell application "Notifications Scripting" to display notification "Fallen London" message "You have " & newActions & " new actions!" sound name "Glass"
        end if
        set newActions to 0
    end if
    return delayTime
end idle

【问题讨论】:

  • 告诉我们更多关于它何时触发的信息。触发是否一致?

标签: applescript osx-elcapitan idle-timer


【解决方案1】:

我不希望您的 idle 实现能够可靠地工作。它不是一个精确的计时机制;因此,以下假设是不合理的:

if ((seconds of (current date)) = 24) and ((minutes of (current date)) mod 10 = 3) then

您在这里尝试在 10 分钟的循环中点击一个 1 秒的窗口,如果您错过了该窗口,则需要再过 10 分钟才能重试。

一种可靠的方法是存储一个表示下次触发时间的日期,然后定期检查当前日期是否在该日期之后,如果是则触发:

to nextTriggerDate() -- returns next xx:x3:23 date
    set d to current date
    set {d's minutes, d's seconds} to {((d's minutes) div 10 * 10) + 3, 23}
    if d < (current date) then set d to d + 10 * minutes
    d
end nextTriggerDate

property _triggerDate : nextTriggerDate()


on idle
    if (current date) > _triggerDate then
        set _triggerDate to nextTriggerDate()
        -- DO STUFF HERE...
    end if
    return 1
end idle

或者,您可以通过专为此类任务设计的 AppleScript-ObjC 桥接器使用 NSTimer,或者如果您不希望设置一个 launchd 脚本以在指定时间运行 AppleScript绑定到一个保持打开的小程序。

【讨论】:

    【解决方案2】:

    我认为您的代码存在一些问题。

    首先要注意的是,只有idle 处理程序中的代码才会在每个空闲事件上被调用。换句话说,如果您希望脚本的主体与每个空闲进程一起运行,那么它不会。

    以这个为例……

    on run
        display dialog "hello!" giving up after 3
    end run
    
    on idle
        display dialog "Idle test!" giving up after 3
        return 5
    on idle
    

    当您将上面的代码保存为stay open 脚本时,您会看到一个显示“hello”的对话框,然后您会看到“Idle test!”消息多次,直到您退出脚本。 记得将其保存为“保持打开状态”

    要解决此问题,如果您希望 idle 处理程序之外的所有代码都能运行,请使用它创建一个您从空闲处理程序调用的自定义函数。

     on yourCustomFunction()
         -- All the code you want to run prior when the idle function is called
     end yourCustomFunction
    
     on idle
        yourCustomFunction()
        -- any other additional code you want to run here
        return 5
     end idle
    

    我想指出的另一件事。你不需要tell application "Notifications Scripting",你可以display notification,如下图。

    on idle
        if ((seconds of (current date)) = 24) and ((minutes of (current date)) mod 10 = 3) then
            set newActions to (newActions + 1)
            set delayTime to 540
        else
            set delayTime to 0.5
        end if
    
        if newActions ≥ actions then
            if newActions = 1 then
                display notification "You have " & newActions & " new action!" with title "Fallen London" sound name "Glass"
            else
                display notification "You have " & newActions & " new actions!" with title "Fallen London" sound name "Glass"
            end if
            set newActions to 0
        end if
        return delayTime
    end idle
    

    最后,我建议添加一个on run 处理程序,而不是在没有它的情况下在脚本中编写代码。

    【讨论】:

    • 通知脚本是一个特殊的应用程序,它允许我在单击通知时运行处理程序。没有它,这种行为是不可能的。
    • 空闲处理程序之外的代码旨在在启动时运行,并且不再运行。
    • @Saklad5 - 好的,“通知脚本”的语法与我认为您打算使用的显示通知的语法非常相似。至于空闲处理程序之外的代码,我会确保将其包装在on run 中以使其更清晰。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    相关资源
    最近更新 更多