I have a command line project in Xcode 9 and I'm trying to read a text file I added to the project via "Add files to...". I'm using the following line to grab the path to the file:
guard let filePath = Bundle.main.path(forResource: "stops", ofType: "csv") else {
fatalError("Cannot find CSV file")
}
When I run it, it prints out the fatalError message. I tried adding the text file in the "Copy Bundle Resources" build phase. It still doesn't find the file.
What am I doing wrong?
Early last year I had this same issue - here is my workaround (and I must stress that this is a work around, hopefully there is another way to do it now)
Create a Swift file in your project that you can use to access the data (mine was Recipe.swift)
Drop your CSV into xcode (ignoring target membership - just for convenience (mine was Recipe.json))
Create a run script phase to load the data from your CSV to into a Swift class:
set -e
DATA=$(cat "./MyProject/recipe.json" | base64)
echo "import Foundation" > "./MyProject/Recipe.swift"
echo "class Recipe {" >> "./MyProject/Recipe.swift"
echo " static let data = \"$DATA\"" >> "./MyProject/Recipe.swift"
echo "}" >> "./MyProject/Recipe.swift"
This generates a class in your Swift file that looks something like:
import Foundation
class Recipe {
static let data = "..."
}
And then you can decode Recipe.data when you need to use it.
Of course this isn't a very expandable solution, and I'm sure you can make it better by using lazy initialization, adding the base64 decode directly in the generated class, making paths in the script relative to $SRCROOT etc. This was just my quick solution that allowed me to continue working on the rest of the project.
The issue for me was I have created first a ResponseJSON.swift then rename it to ResponseJSON.json (changed to .json extension) and it was not being detected.
Solution:
Remove the reference of the file
Adding it again on Xcode
Compile and smile while you cry with those Xcode bugs :)
Related
I am trying to load a .obj file into Xcode so I can load it using ModelIO.
I got a .obj file, along with a .model and .mtl file, from a website offering free 3D models. (unfortunately I can't remember the name, but I'm sure it's not important) I placed all 3 files into Assets.xcassets.
Then I use the following code to try and load the file. The OBJ file is specifically called "car.obj":
let modelURL = Bundle.main.url(forResource: "car", withExtension: "obj")!
It should be returning a URL that I can use to create an MDLAsset with, but if I try to build the app it just shows the following error:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an
Optional value
Which implies that the file was not found, according the Apple's documentation. This leads me to believe I haven't imported the file properly, or I have a corrupt file. Any ideas?
No need placed to Assets.xcassets. Try placed into project folder. Just like onimage
I am trying to read text from a file and I am currently using this statement to read from a file.
When I try to print the path it shows 'nil' and I am not sure why it is not opening the file since it prints the else statement. Can someone tell me how I can go about doing this possibly another way?
if let path = Bundle.main.path(forResource: "knapsack", ofType: "txt")
{
print("File opened")
}
else
{
print("failed to load file from bundle")
}
The solution that worked for me was to add the text file in the product path that is located in Library -> Developer -> Xcode -> Derived Data -> "Your Project" -> Build -> Products -> Debug.
I added the file to this path and this solved issue and had no issue opening the file. I guess Xcode has two different paths that needs to have a file added.
1- create a file named knapsack.txt
2- drag the file to project and select copy
3- reference the file as you currently do
see demo here readFile
Long story short, I have two settings files that must have the same name. They're currently in separate folders, something like:
Resources/brand/dev/settings.file
Resources/brand/prod/settings.file
However I can't seem to get Swift to grab the file out, it always comes up as nil
var file = Bundle.main.path(forResource:"settings", ofType:"file", inDirectory:"Resources/brand/dev")
If I remove one of the files, and the inDirectory parameter everything works fine.
File target membership, project build phases all look OK.
Am I missing something here?
Setting files must be added to XCode with the option 'Create folder references'
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!
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.
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"
I'm just trying to begin develop a game in Marmalade (6.3). But when I have made my new sources (.cpp, and .h) and added them to the mkb, and then trying to run my program, then I got an error which says that Unable to find file.cpp in path(s). It's for all of my files except the files (game.h, game.cpp, main.cpp) which were made by Marmalade when I have chosen the new 2D game project. Should I add my .cpp and .h files to anywhere else?
Thanks
It is difficult to give a categorical answer without more info. However my guess is that you've copied and pasted from an example and not understood about the syntax of the files section. Basically:
files
{
(foo)
humbug.cpp
)
The "(foo)" might look very innocent, but it actually says that humbug.cpp is actually in directory foo - relative to the mkb file. It is common practice to actually use "(source)" and put all the source files in a directory of that name - making the source layout a bit neater.
Naturally if you have (source) and don't put the files actually in directory source, they won't be found. My guess is that is what you are seeing.
Just to clarify previous answer, The format of files directive is like this -
files
{
(<Path relative to MKB>,<Alternate Path>)
["Name of the parent Group in VS/XCode project","Name of the subparent group"]
fileName.cpp
fileName.h
}
for example I have two files SoundManager.h and SoundManager.cpp in System folder of Source, while MainMenu.h and MainMenu.cpp in Source/UI. Now the files directive would be -
files
{
(Source/System)
["Source","System"] #This part is not required, it's just to arrange your files in IDE project
SoundManager.h
SoundManager.cpp
(Source/UI)
("Source","UI")
MainMenu.h
ManinMenu.cpp
}