How to access files at a path NSURL - ios

Hello everyone i have the following code :
NSString* issuePath =[[self contentURL] URLByAppendingPathComponent:#"magazine"].path;
I have a file called a.plist in the above directory. I have to read the a.plist file contents. How to do that. Before the file was local and I was accessing it as follows
NSString *path = [[NSBundle mainBundle] pathForResource:#"a" ofType:#"plist"];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"a.plist"];
NSMutableDictionary *plistContents = [[NSMutableDictionary alloc] initWithContentsOfFile:path];

Refer this file handler utility which provides API's to interact with most of your file related operations.
It exposed API for below features,
Check if the file, or directory, exists in the given path
Create a folder in a given path
Verify if a folder exists at a given path
Get the size of a file
Check if a file with that name exists in the folder
Check if this folder has more subfolder or if it's the last folder
File Handler Utility Class link

You can simply use the following method.
NSString *path = [[NSBundle mainBundle] pathForResource:#"a" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];

Related

Accessing plist file by main bundle vs Documents directory

What is the best way to get property list?
1 - From main bundle, i.e.:
NSString *path = [[NSBundle mainBundle] pathForResource:#"recipes" ofType:#"plist"];
 
2 - Or get path from Documents directory, i.e.:
// Data.plist code - get path from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our plist file.
NSString *plistPath = [documentsPath
stringByAppendingPathComponent:#"Data.plist"];
// check to see if Data.plist exists in documents
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
// if not in documents, get property list from main bundle
plistPath = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"plist"];
}
What and why?
And if both are correct then why do we not use 1st one with just one line of code?
Simple rule:
If the property list file is read-only put it in the bundle.
If the property list file is going to be mutated put it in the document directory.

Play audio from created directory

Hi I'm using the following code to play an audio file
NSString *stringPath = [[NSBundle mainBundle]pathForResource:#"audioFileName" ofType:#"mp3" inDirectory:#"/Downloads"];
NSURL *url = [NSURL fileURLWithPath:stringPath];
NSError *error;
avPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
avPlayer.delegate = self;
[avPlayer play];
But I get an error because my audio files I located in a folder called "Downloads"
Path: AppName/Library/ApplicationSupport/Downloads/audioFileName.mp3
The error I get is that the string stringPath is nil probably because that line of code is written wrong. I know for sure the file is there!
Heres an image using file browsing software
So my question how do i modify the above code to point to my downloads directory when playing a audio file. Thanks
Ive even tried putting the whole path like this.
NSString *stringPath = [[NSBundle mainBundle]pathForResource:#"audioFileName" ofType:#"mp3" inDirectory:#"Library/Application Support/Downloads"];
Status update!
I now do the following and the error is gone but not sure if its pointing to the correct folder still and if so is it possible I don't have permissions to use the files within it. This is a directory i created so is changing permissions to it after its created something I had too do?
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryDirectory = [paths objectAtIndex:0];
NSString *stringPath = [[libraryDirectory stringByAppendingPathComponent:#"Downloads"] stringByAppendingPathComponent:#"audioFileName.mp3"];
I believe pathForResource is only for files you include with your app. You have made the audio file in the Library folder which is not in your .app folder... so you could try to use something like:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryDirectory = [paths objectAtIndex:0];
NSString *stringPath = [[libraryDirectory stringByAppendingPathComponent:#"Downloads"] stringByAppendingPathComponent:#"audioFileName.mp3"];

Why can't I retrieve my plist file?

I have a plist file I just created of strings; it looks like this:
This is the code I'm using to create the path to the file:
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); // Create a list of paths
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get a path to your documents directory from the list
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"NailServices.plist"]; // Create a full file path
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]) { // Check if file exists
// Get a path to the plist created before in bundle directory (by Xcode)
NSString *bundle = [[NSBundle mainBundle] pathForResource: #"NailServices" ofType: #"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error]; // Copy this plist to your documents directory
}
This is the code I'm using to examine the data (to make sure this is working)... I'm getting a (null) back from the NSLog statement)
//Load Dictionary with wood name cross refference values for image name
NSString *plistDataPath = [[NSBundle mainBundle] pathForResource:#"NailServices" ofType:#"plist"];
NSDictionary *NailServicesDictionary = [[NSDictionary alloc] initWithContentsOfFile:plistDataPath];
NSLog(#"\nnailServicesDict: %#", NailServicesDictionary);
This is my first attempt at creating/using a "strings" plist file; I have read everything I could find on Google and SO without finding an example of a plain ol' strings file. What else do I have to do to be able to get to this plist data?
Your problem is that you are creating an NSDictionary while your plist is an NSArray. Thus, it will return nil when you try to create it as a dictionary because no dictionary exists.
You need to change:
NSDictionary *NailServicesDictionary = [[NSDictionary alloc] initWithContentsOfFile:plistDataPath];
to
NSArray *NailServicesArray = [[NSArray alloc] initWithContentsOfFile:plistDataPath];
As a commenter posted, plist files can either have an NSArray or an NSDictionary as their root. Your example plist has an NSArray as its root, so you'll want to alloc and init an NSArray, not an NSDictionary. If your plist is stored in the app bundle when you build the app in Xcode and you don't need to modify it at runtime, then it's unnecessary to copy it to the NSDocumentsDirectory. Also, I'd recommend using [paths lastObject]; rather than [paths objectAtIndex:0];, which can throw an exception if the paths array is empty.

pathForResource is empty in iOS

Can't understand, why does this line of the code return (null)?
// Get path of data.plist file to be created
plistPath = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"];
I need to create new plist but can't understand, does the empty file should be created before to get the path to it.. Any ideas?
PS I had only h,m and no plist files in my project now.
You don't create new files in your bundle after deployment. The bundle contains all the resources and files that ship with your app.
Instead, you create new files in your app's Documents folder. To get the documents folder path, you can use a method like this (as included in some of the app template projects):
- (NSString *)applicationDocumentsDirectory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
Then you simply append the file name you want to use.
NSString *path = [self applicationDocumentsDirectory];
path = [path stringByAppendingPathComponent:#"data.plist"];
You might also want to have some additional folders in your Documents folder for organizational purposes. You can use NSFileManager to do that.
Yes, your guess was right - you would need to create a file first. Here is what the class reference documentation had to say about the method's return value
"Return Value
The full pathname for the resource file or nil if the file could not be located."
You could do something like:
if ( [ [NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"] )
plistPath = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"];
else
// Create new file here
Also, you could leave out the type extenxion in the method call above if you are searching for a unique file name.
Source: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/Reference/Reference.html

.plist path on iOS device

-(void)login{
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:#"login" ofType:#"plist"];
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
[plistDict setObject:#"si" forKey:#"stato"];
[plistDict writeToFile:path atomically: YES];
}
In iOS Simulator the plist has been correctly written, but when I try to write the .plist on my iPhone, it doesn't work. I guess it is because of the wrong .plist path.
Do the iOS devices use different path?
First you have to check if the file exits in your documents directory. If it doesn't exits there then you can copy it to the document directory. You can do it this way
-(void)login{
BOOL doesExist;
NSError *error;
NSString *filePath= [[NSBundle mainBundle] pathForResource:#"login" ofType:#"plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString * path =[[NSString alloc] initWithString:[documentsDirectory stringByAppendingPathComponent:#"login.plist"]];
doesExist= [fileManager fileExistsAtPath:path];
if (doesExist) {
NSMutableDictionary* plistDict=[[NSMutableDictionary alloc] initWithContentsOfFile:path];
}
else
{
doesExist= [fileManager copyItemAtPath:filePath toPath:path error:&error];
NSMutableDictionary* plistDict=[[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
}
[plistDict setObject:#"si" forKey:#"stato"];
[plistDict writeToFile:path atomically: YES];
}
You can't write to the [NSBundle mainBundle] location. In order to write files like a plist, you should save in the documents folder, this way:
NSArray *arrayPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *filePathToSave = [arrayPaths objectAtIndex:0];
If the plist is part of your app, I would recommend you, in the first launch, to already copy it to the documents folder using the same filePathToSave, so you will always look at it there, both to read or to save.
This is a big mistake, as the main bundle only is readable and only composed at compile time in the App Bundle. The App Bundle lives in a separate place, whereas the data you should write to disk should be placed into the Documents, Temporary or Library folder of your sandbox.
To gain more understanding please read the official File System Programming Guide.
Everything you need to know is written there.
You can also write to subfolders and you should choose between the 3 above mentioned main directories in terms of backing up, when syncing with iTunes or iCloud. For instance contents in the tmp Folder won't be backed up.
You can not write to the mainBundle on an iOS device. You will have to save the file to a directory and modify it there.
Just to bring the answers into the modern world - you should really be using the URL based methods for getting directories:
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSURL *URLForDocumentsDirectory = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]

Resources