Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos Cocoa脚本:使用特殊的字符串类型,如原始数据_Macos_Cocoa_Applescript_Cocoa Scripting - Fatal编程技术网

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

Macos Cocoa脚本:使用特殊的字符串类型,如原始数据,macos,cocoa,applescript,cocoa-scripting,Macos,Cocoa,Applescript,Cocoa Scripting,我的应用程序有一些原始数据内容,我希望能够提供给AppleScript,这样它至少可以被查看,即使不需要将其保存到文件或设置为支持它的其他对象 现在,我不知道使用哪种数据类型来实现这一点 查看脚本编辑器的输出,例如: tell application "Script Editor" the clipboard as record --> {Unicode text:"text", «class BBLM»:«data BBLM6C6C756E»,

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

现在,我不知道使用哪种数据类型来实现这一点

查看脚本编辑器的输出,例如:

tell application "Script Editor"
  the clipboard as record
    --> {Unicode text:"text",
         «class BBLM»:«data BBLM6C6C756E»,
         string:"text"}
end tell
如何返回这些«数据…»,它们显然是实际数据的4字符编码和十六进制字符串编码字节的组合

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

更新

它似乎与实现
scriptingDescriptor
scriptingWithDescriptor
有关。除了在草图示例代码中使用之外,我找不到任何关于此的文档。如果我碰巧在Sdef中定义了这样一个自定义类型,我假设将为该类型调用这些


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

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

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

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

-(id)returnSomeBytes {
    return [NSAppleEventDescriptor descriptorWithDescriptorType:'Raw ', myNSDataObject];
}
这将在AppleScript中以
«数据原始…»
结束

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

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

RE:“…实现scriptingDescriptor和scriptingWithDescriptor。我找不到任何有关此的文档…”

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

- (id)valueWithUniqueID:(id)uniqueID inPropertyWithKey:(NSString *)key
讨论中说:“如果方法valueInWithUniqueID:存在,将调用它。”

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

scriptingDescriptor和scriptingWithDescriptor是在应用程序的.sdef中使用元素时使用的特殊转换处理程序,这就是为什么它们显示在草图中以处理typeRGBColor数据类型,即3个整数的列表。我也无法在草图代码之外找到这些文档,但我可以确认这一点

scriptingRGBColorDescriptor
由中的方法调用:

NSObject(NSScriptAppleEventConversion)
NSAppleEventDescriptor(NSScriptConversion)
RE:“但是:我不知道要提前发送的类型,因此我无法在Sdef中预先定义它们。”

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

这是我去年在ASOC邮件列表上发布的一个项目:

下面是从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

end

NSData
对象用于符合
NSCoding
的自定义
值类型
,这些值类型不能由AppleScript支持的基本类表示。例如,基本的AppleScript类型
point
rectangle
是用
NSData
包装的C类型。要定义自定义的
值类型
,您必须在sdef文件中提供目标类,并在目标类的一个类别中实现
脚本…
方法。在根据您在我的另一个问题()中的评论进行进一步挖掘后,我终于明白了您的意思,但我还没有理解,也就是说,这一切都归结为使用NSAppleEventDescriptor,这是每个Cocoa类型在将值返回到正在运行的Applescript之前最终被分配到的类型。确切地说,Cocoa脚本可能是一件很棒的事情,但文档记录很差,而且很容易出错。在瑞士这里,我们会说“s'isch en saich”(类似于“屁股痛”),所以,感谢你的帮助,没有你的指点,我还没有弄明白这一点,尽管现在一切都是如此“当然,这完全有道理!”:)我希望这也能帮助其他人。对于那些像以前一样使用Cocoa层的人来说,这可能都是显而易见的东西,但我完全被难住了。我的测试表明,即使你没有实现
scriptingWithDescriptor
函数,您将通过
valueWithUniqueID:
处理程序获得原始的
NSAppleEventDescriptor
,然后您可以从中提取
数据和
描述符类型。一旦在Sdef中为属性指定了特定类型,就有必要实现
scriptingDescriptor
。如果使用“any”作为类型,则不需要这样做。这似乎证实了它们是作为描述符强制过程的一部分被调用的。当您指定“any”类型时,您就是