You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何强制立即调用AppleScript的idle handler并生效新频率?

如何让AppleScript的idle handler修改频率后立即生效?

问题描述

我并非资深AppleScript开发者,目前正在学习并尝试使用idle handler。通过查阅资料,我编写了一个常驻脚本,其idle handler每20秒被调用一次(为简洁未添加错误处理),脚本带有菜单栏选项可修改handler的调用频率。

代码运行正常,但修改后的调用频率无法立即生效,需等待下一次idle handler被调用时才会启用新频率。我希望能强制立即调用该handler并让新频率即时生效,请问这是否可行?

原代码:

--******************* Begin Timer Code *******************
global sleepTimeSeconds
set sleepTimeSeconds to 20

on idle
    say "Hi!!  I'm awake now."
    
    return sleepTimeSeconds
end idle
--******************** End Timer Code ********************

--****************** Begin MenuBar Code ******************
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

-- init new menu bar to build menus from scratch
set menubar to current application's NSMenu's alloc()'s init()

-- clear predefined menus
set menuBarItem to current application's NSMenuItem's new()
menubar's addItem:menuBarItem
current application's NSApp's setMainMenu:menubar
current application's NSApp's mainMenu()'s removeAllItems()

-- make and edit App name's menu 
set asstMenuItem to menubar's addItemWithTitle:"" action:(missing value) keyEquivalent:""
set asstMenu to current application's NSMenu's alloc()'s init()
menubar's setSubmenu:asstMenu forItem:asstMenuItem
set quitMenuItem to asstMenu's addItemWithTitle:"Quit" action:"actionHandler:" keyEquivalent:"q"
(quitMenuItem's setTarget:me)

-- make and edit "File" menu 
set asstMenuItem to menubar's addItemWithTitle:"" action:(missing value) keyEquivalent:""
set asstMenu to current application's NSMenu's alloc()'s initWithTitle:"File"
menubar's setSubmenu:asstMenu forItem:asstMenuItem
set openMenuItem to asstMenu's addItemWithTitle:"Show Sleep Time Seconds" action:"actionHandler:" keyEquivalent:"t"
(openMenuItem's setTarget:me)

-- make and edit "Edit" menu
set asstMenuItem to menubar's addItemWithTitle:"" action:(missing value) keyEquivalent:""
set asstMenu to current application's NSMenu's alloc()'s initWithTitle:"Edit"
menubar's setSubmenu:asstMenu forItem:asstMenuItem
set openMenuItem to asstMenu's addItemWithTitle:"Edit Sleep Time Seconds" action:"actionHandler:" keyEquivalent:"e"
(openMenuItem's setTarget:me)

on actionHandler:sender
    set theMenuItemTitle to title of sender as string
    if theMenuItemTitle is "Quit" then quit
    if theMenuItemTitle is "Show Sleep Time Seconds" then
        showSleepTimeSeconds(theMenuItemTitle)
    end if
    if theMenuItemTitle is "Edit Sleep Time Seconds" then
        editSleepTimeSeconds(theMenuItemTitle)
    end if
end actionHandler:

on showSleepTimeSeconds(theMenuItemTitle)
    display alert "Sleep Time = " & (sleepTimeSeconds as string) & " seconds." giving up after 3
end showSleepTimeSeconds

on editSleepTimeSeconds(theMenuItemTitle)
    try
        set theResultReturned to (display dialog "Provide new Sleep Time in seconds:" default answer (sleepTimeSeconds as string) buttons {"Save", "Cancel"} default button "Cancel")
    on error
        showSleepTimeSeconds(theMenuItemTitle)
        return
    end try
    
    set theTextReturned to the text returned of theResultReturned
    set theButtonReturned to the button returned of theResultReturned
    if theButtonReturned = "Save" then
        set sleepTimeSeconds to theTextReturned as number
    end if
    showSleepTimeSeconds(theMenuItemTitle)
end editSleepTimeSeconds
--******************* End MenuBar Code *******************

解决方案

可以实现,只需在修改完间隔时间后,手动调用一次idle handler,并通过AppKit的API重置空闲计时器,就能让新频率立即生效。

修改后的关键代码部分:

on editSleepTimeSeconds(theMenuItemTitle)
    try
        set theResultReturned to (display dialog "Provide new Sleep Time in seconds:" default answer (sleepTimeSeconds as string) buttons {"Save", "Cancel"} default button "Cancel")
    on error
        showSleepTimeSeconds(theMenuItemTitle)
        return
    end try
    
    set theTextReturned to the text returned of theResultReturned
    set theButtonReturned to the button returned of theResultReturned
    if theButtonReturned = "Save" then
        set sleepTimeSeconds to theTextReturned as number
        -- 新增:立即触发idle并重置计时器
        my idle()
        current application's NSApp's resetIdleTimer()
    end if
    showSleepTimeSeconds(theMenuItemTitle)
end editSleepTimeSeconds

原理说明

  • 手动调用idle handler:修改完sleepTimeSeconds后直接执行my idle(),会立即触发一次任务执行,同时让idle返回新的间隔值。
  • 调用resetIdleTimer():这个AppKit方法会让系统抛弃原来的剩余等待时间,立即基于新返回的间隔值重新计算下一次idle的触发时间,确保新频率即时生效。

内容的提问来源于stack exchange,提问作者Uncle Bill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:04:52