【问题标题】:In macOS AppleScript, how do I check if a property exists?在 macOS AppleScript 中,如何检查属性是否存在?
【发布时间】:2020-06-04 19:10:17
【问题描述】:

在 AppleScript 中,我访问应用程序中的对象,例如:

tell application id "DNtp"
  repeat with g in (children of root of (think window 1))
       set theAnnotation to annotation of g
  end
end tell

我知道根据访问的孩子,g 有时没有annotation 属性。

注意这与拥有missing value 或类似的东西不同

运行代码时,AppleScript 只是抱怨变量 theAnnotation 未定义。

除了使用try ... on error 语句捕获错误之外,我如何检查g 是否具有annotation 属性?

【问题讨论】:

  • AFAIK,香草 AppleScript 不提供类似于例如的内置功能。 JavaScript 的 hasOwnProperty() 方法。
  • @RobC 是的,我确实在考虑使用 JXA 来解决这个问题。谢谢!
  • AS 类比是exists。看我的回答。
  • hasOwnProperty 不太可能有帮助:Apple 事件属性说明符与 JavaScript 属性无关。两种可能性: 1. 应用程序定义了两个窗口“子类”,一个带有annotation 属性,一个没有;如果是这样,请更改您的参考以仅指定前者。 2. 应用程序有问题:它没有返回missing value 来表示“无值”,而是返回一个空描述符或什么都不返回,AS 将其视为字面上没有值。如果是这样,请提交一份错误报告并使用 CRGreen 的列表技巧作为解决方法:repeat with g in (get annotation of children…)
  • 澄清一下,我的第一条评论提到了 JavaScript 的 hasOwnProperty 方法作为示例 - 这并不意味着 JXA 一定是解决方案。

标签: macos applescript


【解决方案1】:

如果你这样做了

tell application id "DNtp"
    annotation of children of root of (think window 1)
end tell

您将获得一个包含注释的列表,如果缺少注释,missing values,例如:

--{missing value, missing value, missing value, «class DTcn» id 49 of «class DTkb» id 1, missing value}

您在 DEVONthink 中描述的问题(AS 在编译时忽略声明的变量)也是我在其他应用程序中看到的问题(但相当罕见)。

如果你想检查一个属性是否存在,通常有效的方法(我已经用 DEVONthink3 测试过)是使用exists,比如:

if (exists annotation of g) then

如您所料,它将返回 true 或 false。不知道你会如何以你第一次发布的方式使用它,但我真的不知道你正在采取的所有步骤,所以....

希望对你有帮助

【讨论】:

  • 您的解决方案是最接近我自己的编程风格的解决方案。很好谢谢。我应该尝试使用 exists,但从 Apple 开发文档中我得到的印象是它不起作用。
  • 我希望我专门为 DEVONthink 提出了这个问题,因为您的解决方案确实与在 SE 上发布此问题的潜在动机最相关。尽管如此,我还是给了你的解决方案一票。另请参阅我上面关于exists 的性质的评论。我在我的 Applescript 中使用了您的解决方案。
  • 你是说我的答案就是解决方案吗?
  • 好吧,我试图解释这一点,但解释分散在 cmets 中。总结一下:发布的问题要求提供适用于每种情况的通用解决方案。 CJK 解决了那个问题。您从应用程序 ID 中认识到它与 DEVONthink 有关,并在我提炼已发布问题的特定情况下为该特定应用程序提供了相关且有效的解决方案。请相信我,我发现很难决定用“已解决”复选标记奖励哪个答案,因为 SE 只允许我选择 1。但我确实赞成你的。
  • 啊,我明白了。很好解释。很高兴我能做出贡献。
【解决方案2】:

我不使用DEVON相关的软件,但是在处理AppleScript记录的普通1情况下,CRGreen的建议将不适用:exists不是一个命令属性理解,尤其是不存在的属性;并且引用不存在的属性会引发错误。

很高兴您正在寻找try...end try 的替代品。我已经看到您以前的代码示例被淹没在其中,当捕获到错误时,它们是昂贵的操作,因此不适合您尝试的操作。 try 在 AppleScript 中根本没有位置。

不是在record 中测试属性的存在,而是在一般情况下解决此问题的方法是创建一个包含所有需要的属性值的record 对象,并分配他们每个人的默认值。

在 AppleScript 中,观察到 record 遵循以下行为:

  • 单个record 对象只能包含一个具有给定标识符的属性。如果您尝试插入两个标识相同的属性,编译器将保留第一个属性及其关联值,并清除其余的:

    {a:1, b:2, a:3} # will resolve on compilation immediately to {a:1, b:2}
    
  • 两个record 对象可以包含具有共享标识符的属性,如下所示:

    set L to {a:1, b:2, c:3}
    set R to {d:missing value, c:L}
    

    list 对象类似,两个record 对象可以合并为一个record,并且属性将被合并:具有每个record 唯一标识符的属性将简单地插入到结果数据结构。如果标识符在合并之前出现在两个 record 对象中,同样,优先级以从左到右的阅读顺序给出,因此以 record 为前缀(在左侧)中的属性将占上风,以 @987654339 为后缀@(右侧)将清除其非唯一的属性标识符(及其值):

    L & R --> {a:1, b:2, c:3, d:missing value}
    R & L --> {d:missing value, c:{a:1, b:2, c:3}, a:1, b:2}
    

您的代码 sn-p 包含以下内容:

repeat with g in (children of root of (think window 1))
     set theAnnotation to annotation of g
end

因此,g 是包含在 childrenlist 对象)中的项目,g 的类型类是 record。根据正在检查children 的哪个项目,我假设其中一些项目是确实 包含annotation 标识的属性的记录,而其中一些项目是不包含这样的属性。

但是,请考虑由此合并产生的以下record

g & {annotation:missing value}

以下是两种可能的情况:

  • g 是一个 record,它已经包含一个标识为 annotation 的属性,例如:

    set g to {cannotation:"doe", bannotation:"ray", annotation:me}
    g & {annotation:missing value} --> {cannotation:"doe", bannotation:"ray", annotation:«script»}
    
    set theAnnotation to annotation of (g & {annotation:missing value})
         --> «script» (i.e. me)
    

    或:

  • g是一个record,其中属性标识符annotation不存在,例如:

    set g to {doe:"a deer", ray:"a drop of golden sun"}
    g & {annotation:missing value} --> {doe:"a deer", ray:"a drop of golden sun", annotation:missing value}
    
    set theAnnotation to annotation of (g & {annotation:missing value})
        --> missing value
    

因此,对于脚本中使用try...end try 来捕获record 数据结构中未出现的属性的每个位置,只需删除try 块,以及在您分配从推测读取的值的任何位置属性值,人为插入默认值,然后您可以测试并知道该值是来自您的 DEVONthink 源还是来自您的大脑:

tell application id "DNtp"
  repeat with g in (children of root of (think window 1))
       set theAnnotation to annotation of (g & {annotation:false})
       if theAnnotation ≠ false then exit repeat
  end
end tell

1这绝不意味着他的解决方案不可行。如果 DEVON 返回的集合没有被取消引用——它很可能会这样做——这些可以作为一个整体进行操作,而不需要遍历单个项目,当然,他使用 DEVON。但是我希望在上面解决的情况是一种更常见的情况,并且在这里也可以使用

【讨论】:

  • @CJK,我不知道 Applescript 中记录的“合并”属性。这是一个非常优雅的解决方案。关于你对@CRGreen 建议使用exists 的评论,我最初是同意你的。但是,正如我在@CRGreen 的回答下面评论的那样,一些实验证实它适用于 DEVONThink 对象。根据“Applescript,权威指南,2nd”p344,exists 命令将由应用程序实现。如果是DEVONThink,就是这种情况,只需通过搜索exists查看字典即可。
  • @CJK 所以,你的解决方案是普遍适用的,这是我问题的背景,因此我必须为你的解决方案投票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-22
  • 2014-08-11
  • 2017-01-15
相关资源
最近更新 更多