I'm developing for iOS. how can I put in a NSMutableArray all file names that are present in the app? Thanks a lot
Try
NSString path = [[NSBundle mainBundle] bundlePath];
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
This should give you content inside the .app folder. If you have files inside subfolders, you'll have to check if the file returned is a file or folder, and get the files inside recursively
Related
I'm trying to access a resource file I added in the app using relative pathing. I've read that I was supposed to use something like this :
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *filePath = [[mainBundle resourcePath] stringByAppendingPathComponent:#"myFile.txt"];
fh = [NSFileHandle fileHandleForReadingAtPath:resourcePath];
Except this isn't working. With NSLog, I am able to confirm mainBundle isn't null and resourcePath returns something like this:
/Users/tom/Library/Developer/CoreSimulator/Devices/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX/data/Containers/Bundle/Application/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX/MyApp_Demo.app/myFile.txt
I've tried many things, such as adding the name of directory where the resource is located, that would be Ressources/myFile, but nothing is yielding any result.
I'm a total beginner with Objective-C but I have to tinker with legacy code and I have to deal with this, so any help is much appreciated.
Side note:
this is what the project structure looks like from Xcode:
Meanwhile, in Finder, the Ressources directory isn't inside the MyApp directory, rather they're on the same level inside the project directory. I wonder if that could be the problem.
Side note 2:
NSString *filePath2 = [[NSBundle mainBundle] pathForResource:#"myFile" ofType:#"txt"];
returns (null) after logging in the console.
It is best to use a simulator for this debugging process
Verification
You should check if the file or Resources folder is actually being copied to the right location or not. If you have added the Resources folder, than check it with the below code
NSString *resourcesFolderPath = [[NSBundle mainBundle] pathForResource:#"Resources" ofType:nil];
NSString *fullFilePath = [NSString pathWithComponents:#[demoToursPath,"filename.txt"]];
NSFileManager *manager=[NSFileManager defaultManager];
NSLog(#"Filepath: %#", fullFilePath);
NSLog(#"File Exist: %#", [manager fileExistsAtPath:fullFilePath]);
Once you have confirmed this, you can update your code to match the location and path it needs to be in order to access the file.
Additional Debug
You can also just print the Document Directory for the application and open a finder window and navigate there to see if the Resources folder is added at the right place (if it was added)
NSString *documentDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]
NSLog(#"Document Directory: %#", documentDir);
If you update the question with more info, I would be able to help you better
This question already has answers here:
Does an iOS app have write access inside its bundle?
(2 answers)
Closed 8 years ago.
beg-counter.txt file is already in my application's bundle....now i wanted to write into it...but i can't....
i can read that file but not able to write into it....
here is my code.......
value of level_beg_cnt is suppose 2.
NSError *error;
NSString *Path = [[NSBundle mainBundle] pathForResource:#"beg_counter" ofType:#"txt"];
NSLog(#"string to write:%#",level_cnt_beg);
[level_cnt_beg writeToFile:Path atomically:YES
encoding:NSUTF8StringEncoding error:&error];
The bundle is read-only. You don't want to mess around with it for two reasons:
Code Signing: the signature is verified by against the contents of the bundle; if you mess around with the bundle, you break the signature.
App Updates: updates work by replacing the entire app bundle with a newly downloaded one; any changes you make will get lost.
Where you should save stuff:
Documents: if you want it to persist and be backed up
Library/Caches: if you just want to cache downloaded data, like profile pics; will be auto deleted by the system if it is low on room unless you specify with a special do-not-delete flag.
tmp: temporary files, deleted when your app is not running
For a full explanation check out File System Programming Guide and QA1719.
From following SO Answer:
You cannot write to applications bundle, it is read-only,
You can write files to document directory.
NSError *error;
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; // or [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *filePath = [docPath stringByAppendingPathComponent:#"beg_counter.txt"];
[level_cnt_beg writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
you can also save files to temp directory and Librarydirectory, for more info read this documentation, Where you should put your files
Thanks
I am building a simple iOS app. And I need to read some data from a text file.
But I don't know where to put it.
I have tried to put it under the Debug-iphoneos or Debug-iphonesimulator. But it doesn't work.
Drag it into your project. When asked if it should be part of the app target, make sure it is. The result is that when you build the app, the file will be copied into the app bundle and thus will make its way onto the target device as part of the app, where your code can retrieve it, along these lines:
NSString* f = [[NSBundle mainBundle] pathForResource:#"myfile" ofType:#"txt"];
NSError* err = nil;
NSString* s = [NSString stringWithContentsOfFile:f
encoding:NSUTF8StringEncoding
error:&err];
The main bundle should work like others have stated, if you want to access it for testing via the documents directory for some testing or other purposes. This should give you the directory for that app:
NSLog(#"%#",[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0]);
Resulting URL for if you decide to put it into the documents folder:
[[[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0]URLByAppendingPathComponent:#"YOUR_FILE_NAME_HERE"] URLByAppendingPathExtension:#"txt"];
I'm using this code to read data from a local (in the XCode project) .plist file.
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"GameData.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"GameData" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error];
}
gameData = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
And it worked great the start, but now I find when I step through the code in the simulator that my game is using a version of the .plist file that existed right at the start, and the new fields I've set up in my new GameData.plist file is not appearing.
I presume that's because it doesn't get the data again if the file already exists? but then how do I get the new version of the .plist file? I tried removing the if statement, but I get a runtime error saying the file already exists.
It sounds like you need to setup a version system. But, the only reason to copy a file from the bundle to the documents folder is so you can edit it, so you need to think about how to merge the updated file in the bundle and the users additions in the documents folder.
Once you have a plan for merging the files, then you can change your if statement so it doesn't just check if the file already exists (if it does, you need to delete it before you can replace it) but also considers the version. You may want to store the currently copied version number in user defaults and add a version number to the file in the bundle. You may also want to keep the user modified data in a different file and use that as overrides.
I'm trying to load a plist file in my application with
NSBundle* bundle = [NSBundle mainBundle];
NSString* plistPath = [bundle pathForResource:#"CategoryData" ofType:#"plist"];
categoryProps = [[NSArray alloc] initWithContentsOfFile:plistPath];
but the categoryProps array always ends up with 0 objects. I've placed the CategoryData.plist file under the "Supporting Files" dir in my project but I can't figure out how files are arranged in the compiled app.
Can someone point me to docs that describe how the file system of an app is laid out and how to figure out where files are located within the file system?
I forgot to point out that I am using XCode 4 which does not create a resources folder for the project
Your loading code code should work for locating the file within the file system. In a project, I have:
NSString *data = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"];
What I would do is log the plistPath to the console or inspect it in the debugger, then navigate to that location on disk and determine if the plist ends up where you think it does.
Also, locate your application bundle in /Users/<# Username #>/Library/Developer/Xcode/DerivedData/<# Unique Appname #>/Build/Products/Debug-iphonesimulator/<# Appname #>.app, right click on it and select "Show package Contents". Ensure that you see your plist where you think you should.
You need to place your plist file in the Resources folder. Then you will be able to load and use them like this
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"Info.plist"];
NSDictionary *plistData = [[NSDictionary dictionaryWithContentsOfFile:finalPath] retain];
UPD: In xcode4 you must to place plist files in the "Supporting Files" directory instead of "Resources". And try to use NSDictionary instead of NSArray