12

I'm trying to get the path of a resource in a Command Line Tool in Xcode (8 beta 2). Here's what I've got:

  • The resource, file.xyz, has been dragged into the project and the target membership matches the main project.
  • Under Build Phases -> Copy Files, the destination is set to "Resources" and the subpath is empty. "Copy only when installing" is unchecked and file.xyz is listed in the table below.
  • In my main.swift file, I have the following code:

    guard let filePath = Bundle.pathForResource("file",
                                             ofType: "xyz",
                                             inDirectory: "Resources") else{
        fatalError("Could not find file")
    }
    

The fatalError is triggered every time. Any ideas? I understand that Command Line Tools don't have an application bundle and that's why the resource is being copied into the Resources folder instead, but my inDirectory argument is a bit of a wild guess… Thanks for reading.

EDIT: My primary goal is to access a resource file (text file, in this case) from a CLT—I'm not attached to this specific way of doing it, so if there's an alternate approach that's great too!

Rogare
  • 3,234
  • 3
  • 27
  • 50
  • 1
    Since a CLI has no bundle (`Bundle.main()` is `nil`!), where should the folder `Resources` come from or where should the folder be located? The parameter `inDirectory` specifies a valid subfolder of the `Resources` folder in the bundle. – vadian Jul 17 '16 at 14:56
  • @vadian Thanks for the comment. I ended up going this direction after reading capikaw's comment here: http://stackoverflow.com/a/3950218/1781058, where he says that Bundle can still be used to link files in CLT targets. – Rogare Jul 17 '16 at 15:07
  • You can link files to be compiled, you can even embed files but you cannot access files via `(NS)Bundle` – vadian Jul 17 '16 at 15:12
  • @vadian OK, just to make sure I understand, you're saying there's no way to access a resource file in a Command Line Tool at all? – Rogare Jul 17 '16 at 15:14
  • I don't want to say *at all*, but definitely not via the bundle. For example it's possible to embed `Info.plist` in a CLI but it's beyond my knowledge how to access it. – vadian Jul 17 '16 at 15:18
  • @vadian OK, thanks. I'll edit my question to be clear that I'm interested in accessing a resource file but not necessarily using Bundle. – Rogare Jul 17 '16 at 15:25
  • 5
    Command line tools *do* use the `Bundle` structure: in other words, `Bundle.main` returns a valid bundle for the directory containing the command line executable. `Bundle.main.resourceURL` returns the url for the parent directory. `Bundle.main.pathForResource("file", ofType:"xyz")` would return a valid path provided `file.xyz` is copied into the same directory as the command line tool. – NSGod Jul 17 '16 at 17:38
  • @NSGod Thanks, that did it! If you want to put that in an answer, I'll mark it as accepted. – Rogare Jul 17 '16 at 18:03
  • 1
    @NSGod For me it seems `Bundle.main` and `Bundle.main.resourceURL` give the directory containing the command line binary. I am not sure how to access other files. – Jay Wang Feb 08 '18 at 21:57

2 Answers2

1

With Xcode 13.2 and Swift 5, I had same issue: I've dragged a JSON file into my Command Line Tool project and was not able to use it directly in my code. As CLT does not seems to have a Bundle, I have found a workaround.

I have created a struct with only a static let property containing my JSON as string:

struct CategoriesJSON {
    static let string = """
... my JSON is here as plain text ...
"""
}

Now I can use it by simply call: CategoriesJSON.string. I know it's a bit ugly, but now my JSON is in my project as I needed.

Jonathan
  • 606
  • 5
  • 19
-2

As a workaround, you can use the absolute path of the source file For example if on iCloud drive :

let path = "/Users/myName/Library/Mobile Documents/com~apple~CloudDocs/myDirectory/file.xyz"

Hugues
  • 164
  • 1
  • 12
  • I don't know why this was voted down. It does work if you're programming for the Mac. You can use it to test importing test files. You can correct my example with the real absolute path for your project. As I said, just a workaround. – Hugues Oct 13 '20 at 16:13