Of course (I struggled with the title, so I can imagine it’s far from apt).
Assume with any snippets below that I will already have imported the appropriate framework to use in an AppleScript, i.e. Foundation
+ ⁄ – AppKit
; and any classes I refer to will be defined as top-level script properties (because I hate typing out current application
more than once).
Given this, in AppleScriptObjC, one can create an NSArray
using an AppleScript list
object. I almost always do it like this:
set L to {true, 2, {pi, "four"}, {5}}
set arr to NSArray's arrayWithArray:L
It can get repetitive. Then when I need to create an NSDictionary
, that really gets on my tits, because I can never write dictionaryWithDictionary:
correctly the first time. But, essentially, there’s a lot of these statements cropping up ad nauseum in virtually every ASObjC script:
set dict to NSDictionary's dictionaryWithDictionary:reco
set str to NSString's stringWithString:txt
set fURL to NSURL's fileURLWithPath:fp
Initially, I simply created an AppleScript handler—one for each class of object—that takes an AppleScript object and spits out a Cocoa object (reference):
to __NSString__(txt as text)
NSString's stringWithString:txt
end __NSString__
…and so on, so creating, for example, an NSArray
would now be possible with:
set arr to __NSArray__({true, 2, {pi, "four"}, {5}})
An NSURL
pointing to a local file URL is now got like so:
set fURL to __NSURL__("~/path/to/file")
where the handler for this looks something like:
to __NSURL__(filepath as text)
NSURL's fileURLWithPath:((NSString's ¬
stringWithString:filepath)'s ¬
stringByStandardizingPath())
end __NSURL__
Now, I’m looking to have one handler that will take an AppleScript object, which can be any of those classes above, and give back the appropriate Cocoa reference. The three examples from my first post illustrate what a proposed handler would be doing when passed a list
and the name of Cocoa class I’m expecting back. For example, I can keep the AppleScript handlers above and use those as selectors, passing its name and the parameter to performSelector_withObject_()
:
to make _nsClass as text with data obj as {record, text, list} : missing value
local _nsClass, obj
if obj = missing value then tell the ¬
current application to return ¬
NSClassFromString(_nsClass)'s new()
set SEL to ["__", _nsClass, "_:"] as text
performSelector_withObject_(SEL, object)
end make
Then it’s possible to Cocoa-fy an AppleScript objects like this:
set arr to make "NSArray" with data {1, 2, 3}
set str to make "NSURL" with data "~/path/to/file"
and if one just wants to initialise an instance of a Foundation type to be returned empty—say, NSMutableArray
—then:
set arr0 to make "NSMutableArray"
arr0's addObject:"foo"
arr0 as list --> {"foo"}
I’m looking for insight and/or advice about whether this is a suitable way to implement this generalised AppleScript-to-Cocoa handler, to which I’m referring to the use of performSelector_withObject_
to achieve this (and not so much to the use of make
I imagine would have Nigel’s eyes rolling a full 360°); or whether one of the other two techniques from my original post are more/less suitable/recommended (I can provide the form that the generalised handlers for those two would take if the specific examples aren’t sufficient to extrapolate this, but basically they look up the name of the Foundation class’s type method used to instantiate and initialise the corresponding Cocoa object, and pass that as the selector used either by performSelector_withObject_
or NSExpression's expressionForFunction:selectorName:arguments:
); or, of course, if there’s another way (NSInvocation
, maybe ?).