我正在尝试编写一个AppleScript,以完成与名称和列表匹配的所有提醒,但如果它们要么没有到期日,要么过期了(到期日<今天)。
我知道我可以循环使用提醒来解决这个问题,但是当有大量提醒时,循环提醒会非常缓慢,所以我想知道如何在一行中完成这个任务,这在我的用例中是多个数量级的。
当我运行这个脚本时:
set curDate to current date
tell application "Reminders"
set myList to "Reminders"
set myTitle to "Test 1"
set completed of every reminder in list myList whose completed is false and name is myTitle and (due date is missing value or due date is less than curDate) to true
end tell我知道这个错误:
error "Reminders got an error: Can’t make missing value into type date." number -1700 from missing value to date这句话的重点是:
set completed of every reminder in list myList whose completed is false and name is myTitle and (due date is missing value or due date is less than curDate) to true我似乎无法让type of due date和missing value的类型匹配,除非创建一个虚拟提醒。注意:以下代码工作正常
set curDate to current date
tell application "Reminders"
set myList to "Reminders"
set myTitle to "Test 1"
-- Create a dummy reminder whose due date is "missing value"
set newremin to make new reminder
set name of newremin to "Debugging delete me"
set completed of every reminder in list myList whose completed is false and name is myTitle and (due date is (due date of newremin) or due date is less than curDate) to true
end tell我创建了两个提醒来测试这一点,两者都被命名为"Test 1“。一个是今天到期的,另一个是没有到期日的。使用虚拟提醒的工作示例成功地完成了这两个提醒,并且运行速度相对较快。
是否有一种方法可以修改1 set completed...行来工作,而不必创建一个虚拟提醒?
发布于 2022-07-15 14:59:29
更新答复
我的第一个答案有一个问题,我想出来了。无论是我的脚本还是另一个答案中的脚本,都不会完成提醒程序中显示为未完成的提醒。我认为这要么是由于一个提醒同步问题(多个设备之间),要么是因为我完成了然后“未完成”的提醒,其中任何一个都会导致重复提醒。
不管原因如何,在这种情况下,every reminder...语句只将搜索条件与一个(而不是提醒程序显示的标准)进行比较。下面的屏幕记录显示,AppleScript从不在提醒应用程序中显示的当前到期提醒上循环:
奇怪的是,那些重复出现的“未来到期”提醒确实会得到评估和返回。我发现,如果我返回每个提醒并搜索结果,我就会发现一个重复的提醒,其到期日与提醒程序中显示的不完整的提醒相匹配,但是返回的提醒的属性显示它是完整的。
此外,给定whose due date is greater than curDate的脚本只返回将来到期的定期提醒,如果在重复中的提醒已经完成,那么“未完成”。
另一个有趣的/奇怪的行为是,如果我不包括whose due date is...,大约一年后返回的一个不完整的提醒显示是到期的,我在实际的sqlite3数据库中找不到这样的提醒。
无论如何,我发现的唯一对这些提醒数据库不一致既快速又健壮的解决方案是从sqlite3数据库中获取提醒ID,并在这些提醒ID上在AppleScript中循环。
我编写了一个perl脚本,用于在sqlite3数据库中找到提醒,尽管我还没有公开发布它。但是,如果您编写了自己的脚本,这里有一个屏幕记录证明,说明要返回什么以及如何使用提醒ID来完成提醒:
我最终将发布我的perl脚本,并且我将尝试在我发布的时候更新这个答案,但是我会说,我得到的AppleScript/PerlScript组合体(到目前为止)似乎总是完成了向它抛出的每一个预期的提醒,不过我将添加一个警告,如果另一个设备的sqlite3数据库在它的sqlite3数据库中有不同的in集,除非它在该设备上运行,否则这个脚本无法完成这些。
同时,下面是我的AppleScript的内容(为简洁而编辑),它显示了对perl脚本的调用:
set status to my completeReminder("Feed the cat", "Reminders")
on completeReminder(myTitle, myList)
set curDate to current date
set fcmd to "perl getReminder.pl -c incomplete -t '" & myTitle & "' -l '" & myList & "' -d future-due --ids"
set ccmd to "perl getReminder.pl -c incomplete -t '" & myTitle & "' -l '" & myList & "' -d past-or-no-due --ids"
try
set future_due to paragraphs of (do shell script fcmd)
set to_complete to paragraphs of (do shell script ccmd)
on error errmsg
return {-1, errmsg}
end try
if (count of to_complete) is equal to 0 then
return {0, "No matching reminders"}
end if
if (count of future_due) is greater than 0 then
-- Version to avoid completing future-due reminders
try
with timeout of 600 seconds
tell application "Reminders"
repeat with remid in to_complete
set rems to (every reminder whose id is remid)
repeat with rem in rems
set rem to item 1 of rems
set completed of rem to true
end repeat
end repeat
end tell
end timeout
on error errmsg
return {-1, errmsg}
end try
else
-- This may or may not actually be faster than the loop using the IDs above - I did not make that comparison, but it was much faster in my previous versions
tell application "Reminders"
set completed of every reminder in list myList whose completed is false and name is myTitle to true
end tell
end if
return {(count of to_complete), (count of to_complete) & " reminder(s) completed"}
end completeReminder旧答案
虽然我还没有想出一种在1行中这样做的方法,但我确实注意到,速度是我希望在1行中这样做的原因,结合另一个答案,我找到了一种解决方案,它的运行速度是使用1行every reminder语句所能达到的速度的2倍,而不需要创建虚拟提醒。
即使使用我的虚拟提醒1行解决方案,我也测试发现,花了一分钟时间才完成的是虚拟提醒创建。1行语句的速度非常快,一旦它有虚拟的提醒,比较一个“缺失的值到期日”与任何到期日的提醒。
我也试图寻找一个现有的虚拟提醒,但仍然,它运行了超过一分钟的时间。我怀疑这是every reminder语句返回的要求,这是一个限制时间的瓶颈。但是,通过更多的测试,我发现我可以快速(大约是7秒)执行一个执行返回的first reminder语句。
我还意识到,我所要做的就是避免完成在未来的中到期的提醒,所以我能够将它与一个first reminder语句结合起来,以确定是否确实存在我不想根据到期日完成的匹配提醒。结果是下面的脚本,它在大约13秒内完成了2次提醒(无到期日和过期到期日)(当没有明确不应该完成的提醒时)。最糟糕的情况是,如果有避免完成的提醒,它将在@Robert Kniazidis的解决方案( 1m30s到2m30s之间)加上7秒内运行:
set curDate to current date
set myList to "Reminders"
set myTitle to "Test 1"
tell application "Reminders"
try
-- If no reminders with due dates to avoid exist, this errors out with an index error on the first line and we can complete every matching reminder regardless of due date in the catch. Otherwise, we continue on with a slow solution...
first reminder in list myList whose completed is false and name is myTitle and due date is greater than curDate
-- If there are reminders to avoid completing, do the slow roll...
try
with timeout of 600 seconds
set theReminders to reminders of list myList whose completed is false and name is myTitle
repeat with theReminder in theReminders
try
set dueDate to (due date of theReminder) as date
if dueDate is less than curDate then set completed of theReminder to true
on error
set completed of theReminder to true
end try
end repeat
end timeout
on error errmsg
return errmsg
end try
on error
-- Complete every matching reminder regardless of due date (very fast)
set completed of every reminder in list myList whose completed is false and name is myTitle to true
end try
end tell这是一个屏幕记录,显示它的运行时间约为13s (与另一种解决方案相比,后者需要1m30s到2m30s)。
注意,如果代码的慢部分出现超时错误,则返回错误字符串。
https://stackoverflow.com/questions/72955922
复制相似问题