"fileURL" Seemingly Exhibits Key-Value Coding Compliance

Related Post: Make array of URLs from an array of POSIX paths

By my understanding, the following JXA code and the equivalent AppleScript code below it, should not work:

furls = $( ["~/Desktop/foo.txt", "~/Desktop/bar/"] )
           .valueForKey( 'stringByStandardizingPath' )
           .valueForKey( 'fileURL' );

ObjC.deepUnwrap( furls.dictionaryWithValuesForKeys(
               [ 'className',  'lastPathComponent', 
                 'absoluteString', 'pathExtension',
                 'path' ] ) );
use framework "Foundation"

my (((NSArray's arrayWithArray:["~/Desktop/foo.txt", "~/Desktop/bar/"])'s ¬
 		valueForKeyPath:"stringByStandardizingPath.fileURL")'s ¬
 		dictionaryWithValuesForKeys:["className", "lastPathComponent", ¬
 				"absoluteString", "pathExtension", "path"]) as record

Yet both produce the following dictionary:
[format]{
“path”: [
“/Users/CK/Desktop/foo.txt”,
“/Users/CK/Desktop/bar”
],
“absoluteString”: [
“file:///Users/CK/Desktop/foo.txt”,
“file:///Users/CK/Desktop/bar”
],
“className”: [
“NSURL”,
“NSURL”
],
“lastPathComponent”: [
“foo.txt”,
“bar”
],
“pathExtension”: [
“txt”,
“”
]
}[/format]

Here are some screenshots of the original JXA and AppleScript scripts and the results of their execution within Script Editor.

What seems to be happening is that the “fileURL” key is somehow accessing a property of each the NSString values in the array. These values represent file paths, and this key seemingly translates to NSURL instances of their respective file URLs. This is not normally possible, as there isn’t supposed to be such a key being observed for the key-value coding of NSString objects; and, were we instead already dealing with NSURL objects, then the “fileURL” property is a boolean value.

Has anybody else come across this, and does anyone have an explanation as to why this is happening ? I presume it’s a bug, and if so, it’s a bug of the very best kind, enabling us to convert an array of posix paths into an array of file URLs in a single pass.


AppleScript version:“2.8”
System version:“12.2.1”
CPU type:“Intel x86-64h Haswell”

Model: MacBook Pro (16-inch, 2019)
AppleScript: 2.8
Browser: Safari 537.36
Operating System: macOS 12

NSString is a class cluster, and its path-related methods tend to return path-related subclasses of NSString. On my Mac, stringByStandardizingPath: is returning an NSPathStore2, and if I call respondsToSelector:“fileURL” on an instance, it returns true.

It’s a private class, and it obviously has private convenience methods such as this. It’s a pretty common thing. What is equally common is that they come and go. I seem to recall that these strings used to be of the NSPathStore class, so there’s been a change in the past few years.

You can use them at your peril. Generally there’s good reason they’re not made public.

1 Like

This is confirmed by the fact that when CK’s AppleScript’s run in Mojave (after some non-break spaces are removed which prevent it from compiling), it errors on the valueForKeyPath: instruction:

It seems fairly transient in general, as the other day, the same scripts threw errors of a similar ilk.

Yes, sorry about this. The formatting—specifically the indentation—on BBCode forums are irksome, as it converts leading tabs to spaces, and removes leading space characters. Inserting a non-tab/non-space character was an attempt at a workaround.

Cheers for the info, Shane.