AppleScriptObjC opens up lots of doors for AppleScript, but it’s not without its quirks. One of them is that it can change the way file references are resolved.
Here is a script that shows the problem:
use AppleScript version "2.4" -- Yosemite (10.10) or later
-- use framework "Foundation"
use scripting additions
set filePath to (path to desktop as text) & "Test.txt"
set theText to read file filePath
The script runs fine (assuming you have a file called Test.txt
on your Desktop), until you uncomment the use framework
line, after which you get the error: “Can’t make current application into type file.” That’s not very helpful.
The solution is to change the code so you build file references using coercions. So, for example:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
set filePath to (path to desktop as text) & "Test.txt"
set theText to read (filePath as alias)
or:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
set filePath to (path to desktop as text) & "Test.txt"
set theText to read (filePath as «class furl») -- a «class furl» is a type of file
Once you know, it’s simple enough to fix.
But what if you have a long script that is well tested, but you would like to add some particular functionality that AppleScriptObjC can supply? Maybe you’re short of time. How can you avoid having to check the whole script for these issues?
One way is to put your AppleScriptObjC code in a library. This has the bonus of making it easily re-usable, too. But there is another, simpler answer: confine the AppleScriptObjC code to a script object.
Here is a simple handler using AppleScriptObjC to change the case of a string:
on makeUppercase(aString)
set aString to current application's NSString's stringWithString:aString
return aString's uppercaseString() as text
end makeUppercase
To add it to a script that doesn’t already use AppleScriptObjC, you will also need to add a use frame "Foundation"
statement, and if it has no use scripting additions
statement already, chances are you will need to add that too. From that point, AppleScriptObjC will be available everywhere in the script.
So here is our orignal script with this handler added:
use AppleScript version "2.4" -- Yosemite (10.10) or later
-- use framework "Foundation"
use scripting additions
set filePath to (path to desktop as text) & "Test.txt"
set theText to read file filePath
set theResult to makeUppercase("hello world")
on makeUppercase(aString)
set aString to current application's NSString's stringWithString:aString
return aString's uppercaseString() as text
end makeUppercase
The file reference works OK, but the handler fails. And if you uncomment the use framework
statement to make the handler work, the file reference fails before it gets that far.
But you can confine the use of AppleScriptObjC to the handler by wrapping the handler in a script object, inside another handler. Here’s the modified code:
use AppleScript version "2.4" -- Yosemite (10.10) or later
-- use framework "Foundation"
use scripting additions
set filePath to (path to desktop as text) & "Test.txt"
set theText to read file filePath
set theResult to makeUppercase("hello world")
on makeUppercase(aString)
script theScript
property parent : a reference to current application
use framework "Foundation"
on makeUppercase(aString)
set aString to current application's NSString's stringWithString:aString
return aString's uppercaseString() as text
end makeUppercase
end script
return theScript's makeUppercase(aString)
end makeUppercase
The file reference works, and so does the handler.
You may wonder about the parent
property. You can comment that line out, and the script will still work. However, if you decide later to use AppleScriptObjC throughout the script and uncomment the original use framework
statement, the handler will stop working without this parent property. Consider it future-proofing.
Using AppleScriptObjC this way does add a tiny amount of overhead, and if you are adding many handlers or they will be called repeatedly, you will be better off adding the use framework
statement at the top and dealing with the issues, if any (in most scripts there won’t be). But for small changes, it’s a quick and painless approach.
1 thought on “Adding AppleScriptObjC to Existing Scripts”
Comments are closed.