【问题标题】:Cocoa Scripting: Accept and return NSDataCocoa 脚本:接受并返回 NSData
【发布时间】:2019-04-26 11:42:47
【问题描述】:

为了在我的可编写脚本的 Mac 应用程序中支持二进制数据交换,如果可能的话,我希望使用 AS-ObjC 桥接器以 NSData 的形式接收和传递数据。

例如,我喜欢在 AppleScript 中实现这段代码:

use framework "Foundation"

set theData to current application's NSData's dataWithContentsOfFile:"/some/binary/file"

tell application "MyApp"
    set raw value to theData
end tell

sdef 包含一个值类型和属性:

<suite name="My Suite" code="Demo">
    <value-type name="ObjCNSData" code="NSDa">
        <cocoa class="NSData"/>
    </value-type>
    <class name="application" code="capp">
        <property name="raw data" code="rawD" type="ObjCNSData">
            <cocoa key="rawData"/>
        </property>

然后我将转换处理程序实现为NSData 的扩展,类似于 Sketch 示例如何将 NSColor 转换为值类型“RGB Color”:

@implementation NSData(DemoScripting)
+ (NSData *)scriptingObjCNSDataWithDescriptor:(NSAppleEventDescriptor *)desc {
    id res = [desc coerceToDescriptorType:'NSDa'];
    // -> res is NULL, which is not getting me any further
}

描述的描述是:

<NSAppleEventDescriptor: 'obj '{
  'form':'ID  ',
  'want':'ocid',
  'seld':'optr'($E0A8430080600000$),
  'from':null()
}>

同样,调用 [NSScriptObjectSpecifier _scriptingSpecifierWithDescriptor:descriptor] 也会返回 NULL。

那么,如何在我的应用代码中获取实际的 NSData 对象?

以及如何将 NSData 对象返回给 AppleScript?

【问题讨论】:

  • NSData 和 AppleScript data 不可互换。但是with data参数的类型不一定是二进制数据。您可以在 sdef 文件中添加 value-type 条目,以将 NSData 转换为 MyAppType 预期的 AS 类型。在您的代码中,theData 清楚地表示 UTF8 编码的字符串。从make 命令返回的NSAppleEventDescriptor 包含指向NSData 实例的指针('optr')。我建议直接询问来自 LateNightSoftware 或 Shane Stanley 的 ASOC 专家 Mark Alldritt
  • 所以你的意思是我应该自己评估“optr”而不是寻找可以为我做的框架函数?我能做到。但这仍然留下了如何返回 NSData 对象的问题。

标签: macos applescript-objc cocoa-scripting


【解决方案1】:

Shane Stanley did indeed know a way,它甚至不需要在我的应用程序中添加额外的代码 - 相反,这一切都可以在 AppleScript 中完成,使用这两个转换函数:

use framework "Foundation"

set nsData1 to current application's NSData's dataWithContentsOfFile:"/etc/hosts"
set asData to my ASDataFromNSData(nsData1)
set nsData2 to my NSDataFromASData(asData)

on ASDataFromNSData(theData)
    set theCode to current application's NSHFSTypeCodeFromFileType("'rdat'")
    return (current application's NSAppleEventDescriptor's descriptorWithDescriptorType:theCode |data|:theData) as data
end ASDataFromNSData

on NSDataFromASData(asData)
    return (current application's NSArray's arrayWithObject:asData)'s firstObject()'s |data|()
end NSDataFromASData

看来rdat 是用于此目的的特殊 AppleScript 类型,框架会自动处理与 NSData 的转换。不过,我找不到在 AE.framework 的标头中声明的那种类型。

不过,我仍然必须在我的应用程序代码中显式处理此 rdat 类型。但我不需要 sdef 中的值类型,并且可以将属性更改为:

<property name="raw data" code="rawD" type="any">
    <cocoa key="rawData"/>
</property>

rdat 的形式返回数据是类似的。我的-rawData 方法:

return [NSAppleEventDescriptor descriptorWithDescriptorType:'rdat' data:myNSData];

这仅在我将属性类型声明为“any”时才有效。如果我使用type="rdat",脚本调试器会将该类型显示为专用的原始数据类型,但在尝试设置或获取脚本中的属性时会出现 -10000 错误。

【讨论】:

  • Xcode 中应该有更多的日志记录可以帮助您确定问题的原因。如果没有,请启用 Cocoa Scripting 调试日志记录。可能有一些转换尝试失败了,您需要为此实现一个方法。
  • 您可以将自己的答案标记为选定/“正确”的答案,因为它对其他用户(比如我自己)也很有用。
  • @CJK 明天提醒我。所以让我在两天后接受我自己的答案,以便其他人仍有机会提供更好的答案。然后删除您的评论(我会删除)以减少混乱:)
  • Thomas & CJK,明天来了又走了! :-)
猜你喜欢
  • 1970-01-01
  • 2015-10-20
  • 2015-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-29
  • 1970-01-01
相关资源
最近更新 更多