Search code examples
objective-cpathapplescriptnsurlapplescript-objc

Cocoa/Objective-C get a HFS path (path:to:desktop) from a posix path (path/to/desktop)


I am on OSX, Objective-C.

I have a path/NSURL like

/Users/xxx/Desktop/image2.png

But i pass it to a third party application that excpects finder pathes like

Harddisk:Users:Desktop:image2.png

Is there any method (i can't find) to convert pathes like that or get them out of an NSURL (if possible without string modifying)?

In AppleScript it is

return POSIX file "/Users/xxx/Desktop/image2.png" -->  Harddisk:Users:xxx:Desktop:image2.png

EDIT: This is pretty much the same: Cocoa path string conversion Unfortunately, the method is deprecated...


Solution

  • There is no (easy) alternative at the moment.

    The function CFURLCopyFileSystemPath is not deprecated, only the enum case kCFURLHFSPathStyle is deprecated but the raw value 1 is still working and avoids the warning.

    I'm using this category of NSString

    @implementation NSString (POSIX_HFS)
    
    - (NSString *)hfsPathFromPOSIXPath
    {
        CFStringRef hfsPath = CFURLCopyFileSystemPath((CFURLRef)[NSURL fileURLWithPath:self], 1);
        return (NSString *)CFBridgingRelease(hfsPath);
    }
    @end
    

    The function works also in Swift. The Swift version is a bit more sophisticated and adds the trailing semicolon representing a dictionary implicitly, here as an extension of URL:

    extension URL {
    
      func hfsPath() -> String?
      {
        if let cfpathHFS = CFURLCopyFileSystemPath(self as CFURL, CFURLPathStyle(rawValue: 1)!) { // CFURLPathStyle.CFURLHFSPathStyle)
          let pathHFS = cfpathHFS as String
          do {
            let info = try self.resourceValues(forKeys: [.isDirectoryKey, .isPackageKey])
            let isDirectory = info.isDirectory!
            let isPackage =  info.isPackage!
    
            if isDirectory && !isPackage {
              return pathHFS + ":" // directory, not package
            }
          } catch _ {}
          return pathHFS
        }
        return nil
      }
    }