Cocoa脚本:使用特殊的字符串类型,如原始数据



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

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

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

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

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

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

更新

它似乎与实现scripting<type>Descriptorscripting<type>WithDescriptor有关。除了草图示例代码中使用的文档外,我找不到任何其他文档。如果我碰巧在我的Sdef中定义了这样一个自定义类型,我假设这些将被调用用于该类型。

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

RE:"…正在实现脚本<Key>描述符和脚本<Key>WithDescriptor。我找不到任何有关此的文档…"

首先要开始的是《Cocoa脚本指南》(2008)中的"键值编码和Cocoa脚本"部分。有一大堆这样的方法将类型嵌入到方法名称中。基金会的NSScriptKeyValueCoding协议参考页面中也记录了许多内容,但您必须阅读"讨论"部分才能找到它们。例如,在:

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

讨论中说:"如果方法valueIn<Key>WithUniqueID:存在,就会调用它。"

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

脚本<键>描述符和脚本<键>WithDescriptor是一种特殊的转换处理程序,当您在应用程序的.sdef中使用元素时会使用它,这就是为什么它们在Sketch中显示来处理类型RGBColor数据类型,即3个整数的列表。我也找不到草图代码之外的这些文档,但我可以确认

scriptingRGBColorDescriptor

由中的方法调用

NSObject(NSScriptAppleEventConversion)
NSAppleEventDescriptor(NSScriptConversion)

RE:"但是:我不知道我想提前发送的类型,所以我不能在Sdef中预先定义它们。"

有一种方法可以解决这个问题:您可以返回一个称为用户字段记录(typeUserField)的特殊列表结构。此记录包括交替的Key和Value描述符,并且不需要在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

结束

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

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

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

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

这将在AppleScript中以«data Raw ...»的形式结束。

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

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

相关内容

  • 没有找到相关文章

最新更新