Read file in Xcode project with Swift - ios

I made a method to read a file from the temporary folder. I use the following lines to get the document's path:
path = NSTemporaryDirectory().stringByAppendingPathComponent(folder)
path = path.stringByAppendingPathComponent(fileName + "." + fileType)
And it works great. My question is: how do I get the path for a file located in the main folders of the Xcode project? They are two text files that I drag and drop from a folder to the Xcode project. I selected the option "copy files if needed" when dropping the files. Thanks!

What you are looking for is app's main bundle. You get a path of a file in it like this:
if let path = NSBundle.mainBundle().pathForResource(fileName, ofType:fileType) {
// use path
}
Keep in mind this folder is read-only so you will need to copy the files to temp or documents folders if you want to make changes.

Update the Swift 3.1 - Thanks #Filip Radelic
if let path = Bundle.main.path(forResource: fileName, ofType: fileType) {
// use path
print(path)
}

Swift 4
if let path = Bundle.main.path(forResource: "imagename.png", ofType: nil) {
print("[check] FILE AVAILABLE \(path)")
}

You would use NSBundle to get your main bundle, then pathForResource(_ name: String?, ofType extension: String?) -> String?.

Related

How to get all png from a specific folder in Xcode?

I would like to get all png in a specific folder in Xcode. I am currently using this code right now to get PNG file.
(Bundle.main.paths(forResourcesOfType: "png", inDirectory: nil) as NSArray).enumerateObjects({ obj, idx, stop in
var path = (obj as! NSString).lastPathComponent
print("Path - ",path)
})
but this get all PNG from all folder for example - Example-1
I would like to get images only inside the Fonts folder. How can i do that ?
As I look at your code, I assume you want to get all image paths from Fonts folder from Bundle App Folder. In this case, you must make your Fonts folder to be Reference Folder (blue icon), not Group folder (yellow icon), like this:
You can drag your folder in your Project Navigator, it will display this box:
Be sure to choose Create Folder References and choose your project target.
The reason is Reference folder is a real folder in your Bundle. All files in Group Folder will be flatted, which mean they are all in the root directory of your Bundle, then you won't know the parent folder of these files.
Then you can use your code to retrieve the png (+ you should specify "Fonts" for inDirectory parameter):
(Bundle.main.paths(forResourcesOfType: "png", inDirectory: "Fonts") as NSArray).enumerateObjects({ obj, idx, stop in
var path = (obj as! NSString).lastPathComponent
print("Path - ",path)
})
Hope this helps.
You need to perform these two steps to achieve your goal.
Pass the folder name in inDirectory argument.
Something like this:
let pngs = Bundle.main.paths(forResourcesOfType: "png", inDirectory: "Fonts")
Make sure that the Fonts directory is added into project as Folder Reference instead of a Group.
Hope this helps

Xcode 10: Load the same .xml file in project target and unit test target

I try to load the same .xml file in project target and unit test target.
It seems to be a similar problem like this question: Xcode. Image resources added to a test target are not copied into the tests bundle
In project target, this code snipped worked fine. I just have to add the "xmlString.xml" file to "Copy Files" (see image 1).
func parseFile() {
let stringPath = Bundle.main.path(forResource: "xmlString", ofType: "xml")
let url = NSURL(fileURLWithPath: stringPath!)
...
}
If I run the code snipped in unit test target, I get an error because the .xml file can not be found. I tried to add the .xml file to the "Copy Bundle Resources" without any success (see image 2).
The only way to get it working is to use the absolute path
func parseFile() {
let stringPath: String? = "/Users/.../Documents/Git/.../.../.../.../xmlString.xml"
let url = NSURL(fileURLWithPath: stringPath!)
...
}
Is there a way to use the Bundle.main.path(forResource: "xmlString", ofType: "xml") function instead of the absolute path?
Thanks in advance!
You can get the bundle for your project like this:
let projectBundle = Bundle(for: AnyClassInMyProject.self)
where you replace AnyClassInMyProject with the name of an actual class in your project.
You can then get the path to your .xml file like this:
let stringPath = projectBundle.path(forResource: "xmlString", ofType: "xml")

Bundle.main.path(forResource:ofType:inDirectory:) returns nil when directory and filename are correct

let audioPath = Bundle.main.path(forResource: songs[indexPath.row], ofType: ".mp3", inDirectory: "Songs")!
Returns nil. songs[indexPath.row] returns the correct name, as it is exactly in the folder named "Songs". The songs folder is blue and shows up correctly in my build phases->copy bundle resources
I replied in the comment above but I should go to this place to upload the image and recap my opinion again:
make sure you removed the dot .: mp3 instead of .mp3
songs[indexPath.row] value must not be optional, because it can cause a string like this: Optional(MyFileName), and the value must not contains the extension .mp3, just filename only.
Look at the picture below, if you Bundle.main equivalence is not a selected target in the list of File Inspector, the audioPath may be nil. So you have to check them for all of your mp3 files.

pathForResource returns nil

I have two files, both named GoogleService-Info.plist. One is inside the folders Resources -> Staging and another is in the folders Resources -> Production. They're both added to Copy Bundle Resources. My code to access one of them is this:
if let path = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist", inDirectory: "Resources/Staging") {
print("this should work but doesn't")
}
It always returns nil. Why can it not find the file?
The resources will be put in the root of your app bundle. The only time you will get folders inside your app bundle is when you create folder references in your project. These will be blue folders, not yellow.
Change your code to (remove the inDirectory part):
if let path = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist") {
print("this should work but doesn't")
}

Scanning the contents of a directory which is stored in an Xcode project in swift

This seems to be a problem which is very difficult to explain. I am trying to read data from a folder full of files and the way I am trying to do this is by scanning the whole directory for all of the files. The file in question is stored in my Xcode project in the same directory as the view controllers and storyboards. Like so:
I would like to be able to scan the contents of the "data" folder. Consider the following code:
var tmpDir = NSTemporaryDirectory()
var error: NSError?
let filesInDirectory: [String]! = fileManager.contentsOfDirectoryAtPath(tmpDir, error: &error) as? [String]
This scans the contents of the app's local folder and returns it as an array of the file names. I would like to be able to do this with the "data" folder in my Xcode project. The following code will find the contents of a single file which is stored in the same directory as the "data" folder.
let files = NSBundle.mainBundle().pathForResource("sampleFile", ofType: "csv")
var contents = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)!
Is there a way in which I can combine the capabilities of the two in order to scan the contents of the "data" folder in the Xcode project and then return the file names as an array?
Add the data folder to Copy Bundle Resources in Build Phases of your target.
Then you'll be able to read the path as it's within the same sandbox scope. (Assuming you are applying sandbox.) If not, just use absolute path/URL and you can access it directly without the copying process.
You might want to have a look here: Cocoa contents of directory

Resources