My scriptable app iClip can take clipboard data arguments in the form of raw strings (those that contain both the type as a 4-char-code along with the corresponding data) but it can’t take NSData types currently.
Now, I have data in an ObjC’s NSData object and like to convert it into a raw string so that I can pass that to iClip’s functions that take an “any” parameter.
It’s binary data so I can’t just convert it into a textual string.
How can I do that, provided I know the 4-char type code for it?
use framework "Foundation"
tell application id "org.tempel.xojo.demo.scriptable" -- AppleScriptable.app
set theData to current application's NSData's dataWithContentsOfFile:"/etc/hosts"
set raw data to theData
However, that leads to the error, even before my rawData method is invoked:
Couldn’t write data because C and Objective-C pointers cannot be saved in scripts.
Offending object: «data optr0000000000276300C0600000»
I guess I need some coercion or conversion function somewhere, but I can’t figure out where and how.
Here are handlers for converting from NSData to AppleScript data, and vice-versa:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
set aString to current application's NSString's stringWithString:"one two"
set theData to aString's dataUsingEncoding:(current application's NSUTF8StringEncoding)
set asData to my ASDataFromData:theData
set newData to my dataFromASData:asData
set theCode to current application's NSHFSTypeCodeFromFileType("'rdat'")
return (current application's NSAppleEventDescriptor's descriptorWithDescriptorType:theCode |data|:theData) as data
return (current application's NSArray's arrayWithObject:asData)'s firstObject()'s |data|()
So, I managed to receive these “rdat” raw string in my scriptable app now, i.e. assigning NSData to my app works now. What doesn’t work is the other way around, although I thought that should be easier: Returning NSData (or its rdat equivalent) from my app to a script that wants to get such a value. See my SO answer that is incomplete in this regard: https://stackoverflow.com/a/55870034/43615 - a little help would be great.
I can’t find typeData declared. At least not in AEDataModel.h. Ah - AERegistry.h declares it, but as ‘tdta’!
Sadly, that still leads to error -10000.
What fixes the issue is something else:
Up until now, I declare, in the sdef, the property for the “rawdata” as: type=“rdat”. That seems to be the issue. If I change it to type=“any”, then I can return a data value, and then it does not even matter whether I use ‘tdta’ or ‘rdat’ with the descriptorWithDescriptorType method.
“any” as property type works, although SD’s dictionary viewer shows that as a type, whereas if I’d use “data” or “rdat”, SD shows that as the data type, with a more fitting description of what that type means.
I guess I need to provide a conversion function for this. Just not clear for which types, as there is no explicitly value-type for “data” or “rdat”. Will some try some things.
Could it be that you made a mistake and meant to use “tdta” (typeData)? Because, ‘rdat’ does not appear anywhere in the AE headers as far as I can tell (searched the entire AE.framework headers with BBEdit).
Answer to self: No, only ‘rdat’ works. Any other type won’t convert NSData. It’s magic!
Anyway. In regards to passing raw data to and from my app’s properties, this is good enough. It would be nicer if the property type was actually shown as being of “data” type instead of “any”, but that I can live with.