1

我的应用程序有一些我希望能够提供给 AppleScript 的原始数据内容,以便至少可以查看它,即使不能通过将其保存到文件或将其设置为支持它的其他对象来处理。

现在,我不明白使用哪种数据类型来实现这一点。

请参阅脚本编辑器的此输出,例如:

tell application "Script Editor"
  the clipboard as record
    --> {Unicode text:"text",
         «class BBLM»:«data BBLM6C6C756E»,
         string:"text"}
end tell

我如何返回这些«data ...»,它们显然是实际数据的 4 字符代码和十六进制字符串编码字节的组合。

我尝试从我的脚本属性返回一个包含原始字节数据的 NSData 对象,但这不起作用。

更新

它似乎与实施scripting<type>Descriptorscripting<type>WithDescriptor. 除了在 Sketch 示例代码中使用之外,我找不到任何关于此的文档。如果我碰巧在我的 Sdef 中定义了这样的自定义类型,我假设这些类型将被调用。

但是:我不会提前知道我要发送的类型,所以我无法在 Sdef 中预先定义它们。我的情况更类似于the clipboard:我有想要返回的类似剪贴板的数据,所以我在运行时只知道它们的 4 字符类型。这意味着我不会被这些处理程序询问。必须有其他方法来一般地创建和接收这些类型,就像剪贴板实现一样。

4

3 回答 3

2

回复:“...实现脚本<Key>Descriptor 和脚本<Key>WithDescriptor。我找不到关于此的任何文档...”

首先要从 Cocoa Scripting Guide (2008) 中的“Key-Value Coding and Cocoa Scripting”部分开始。有很多这些方法将类型嵌入到方法名称中。许多也记录在基金会的 NSScriptKeyValueCoding 协议参考页面中,但您必须阅读“讨论”部分才能找到它们。例如,在:

- (id)valueWithUniqueID:(id)uniqueID inPropertyWithKey:(NSString *)key

讨论说:“方法 valueIn<Key>WithUniqueID: 如果存在则调用。”

因此,在 Widgets 类中,您将实现 valueInWidgetsWithUniqueID:

scripting<Key>Descriptor 和 scripting<Key>WithDescriptor 是特殊的转换处理程序,当您在应用程序的 .sdef 中使用元素时使用它们,这就是为什么它们出现在 Sketch 中以处理 typeRGBColor 数据类型,即 3 个整数的列表。我也无法在 Sketch 代码之外找到这些文档,但我可以确认

scriptingRGBColorDescriptor

由以下方法调用:

NSObject(NSScriptAppleEventConversion)
NSAppleEventDescriptor(NSScriptConversion)
于 2016-04-04T04:46:40.727 回答
1

RE:“但是:我不会提前知道我想要发送的类型,所以我无法在 Sdef 中预先定义它们。”

有一种方法可以解决这个问题:您可以返回一个称为用户字段记录 (typeUserField) 的特殊列表结构。该记录包括交替的键和值描述符,并且不需要在 SDEF 中定义任何内容。

这是我去年在 ASOC 邮件列表上发布的一个项目:http: //lists.apple.com/archives/applescriptobjc-dev/2015/Jan/msg00036.html

这是从 NSDictionary 构建 typeUserField 记录的代码(使用 AppleScript-ObjectiveC 代码)。

# ASOC implementation of - (NSAppleEventDescriptor *)scriptingRecordDescriptor for an NSDictionary
# Creates an empty record descriptor and an empty list descriptor, then
# Iterates over the dictionary and inserts descriptors for each key and each value into the list descriptor
# Finally, populates the record descriptor with the type 'usrf' and the list descriptor

on makeUserRecordDescriptor(aDict)

log aDict

set recordDescriptor to aedClass's recordDescriptor()
set listDescriptor   to aedClass's listDescriptor()

set typeUserField to 1970500198 -- 'usrf'

set itemIndex to 1 -- AS records are 1-based

repeat with aKey in aDict's allKeys()

    set aVal to aDict's valueForKey_(aKey)

    -- The values can be several different types. This code DOES NOT handle them all.

    set isStringValue  to aVal's isKindOfClass_(nssClass's |class|) = 1
    set isNumericValue to aVal's isKindOfClass_(nsnClass's |class|) = 1
    set isBooleanValue to aVal's className()'s containsString_("Boolean") = 1

    -- Insert a descriptor for the key into the list descriptor

    set anItem to aedClass's descriptorWithString_(aKey)
    listDescriptor's insertDescriptor_atIndex_(anItem, itemIndex)
    set itemIndex to itemIndex + 1

    -- Insert a descriptor (of the correct type for the value) into the list descriptor

    if isStringValue
        set anItem to aedClass's descriptorWithString_(aVal)
    else if isBooleanValue
        set anItem to aedClass's descriptorWithBoolean_(aVal's boolValue())
    else if isNumericValue
        set intValue to aVal's intValue()
        set fpValue to aVal's doubleValue()

        if intValue = fpValue
            set anItem to  aedClass's descriptorWithInt32_(aVal's intValue())
        else
            set anItem to  aedClass's descriptorWithString_(aVal's stringValue) # TODO: 'doub'
        end
    else
        set anItem to  aedClass's descriptorWithString_("Unhandled Data Type")
    end

    listDescriptor's insertDescriptor_atIndex_(anItem, itemIndex)
    set itemIndex to itemIndex + 1

end

recordDescriptor's setDescriptor_forKeyword_(listDescriptor, typeUserField)

return recordDescriptor

结尾

于 2016-04-05T01:17:50.587 回答
0

神奇之处在于使用NSAppleEventDescriptor. 它提供了很多初始化程序。它是最终保存任何传递回调用 AppleScript(或 JXA 或任何使用脚本引擎的东西)的值的那个。

显然,返回到 Cocoa 脚本层的任何值,例如 NSString 的字符串和 NSNumber 的数值,最终都会分配给 NSAppleEventDescriptor 对象,并通过该步骤转换为 AppleEvent 内部格式。

所以,如果我想返回一个字节串,例如存储在一个 NSData 对象中,我所要做的就是从我的属性方法中:

-(id)returnSomeBytes {
    return [NSAppleEventDescriptor descriptorWithDescriptorType:'Raw ', myNSDataObject];
}

这将在 AppleScript 中以«data Raw ...».

我现在也明白了为什么脚本引擎不会为我自动转换 NSData:它需要一个类型代码,而 NSData 不会继承它。

反过来也一样——任何这样的原始数据都会作为 NSAppleEventDescriptor 传递给我的代码,然后我可以相应地对其进行解码。

于 2016-04-03T14:26:58.610 回答