在 macOS AppleScript 中,如何检查 属性 是否存在?

In macOS AppleScript, how do I check if a property exists?

在 AppleScript 中,我在应用程序中访问 object,例如:

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

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

N.B. 不同于 missing value 或类似的东西。

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

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

如果你这样做

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

这将 return 真或假如您所料。不确定您将如何以您第一次发布的方式使用它,但我真的不知道您正在采取的所有步骤,所以 ....

希望对您有所帮助

我不使用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,并且属性将被合并:具有每个 [=22= 唯一标识符的属性] 将简单地插入而不会对结果数据结构进行任何更改。如果在合并之前标识符出现在两个 record 对象中,同样,优先顺序是从左到右的阅读顺序,因此前缀 record 中的属性(在左侧)将优先并且后缀 record(在右侧)将擦除其非唯一 属性 标识符(及其值):

    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}
    

您的代码片段包含:

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

因此,g 是包含在 children 中的一个项目(一个 list 对象),g 的类型 class 是一个 record。根据正在检查 children 的项目,我假设其中一些项目是 do 包含由 [=40= 标识的 属性 的记录],其中一些项目是 包含此类 属性.

的记录

但是,请考虑此合并产生的以下 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 returns 个未取消引用的集合——它很可能会这样做——这些集合可以作为一个整体进行操作,而无需循环遍历单个项目,当然,他使用的是 DEVON。但我希望在上面解决的情况是一种更常见的情况,并且在这里也适用