Can you build an array of items from folder contents? - iphone

Let's say I've got a folder in my project with bunch of png files in it (or mp3 files, or mov files etc).
I would like to create an NSArray populated with the items within that folder... for instance an array of UIImages for the folder of images (or just an array of NSStrings of the image name).
Is this possible? I know I could create a plist with all the names in, or name the items individually within the code, but this would break the DRY (don't repeat yourself) rule.
Has anyone worked this out?

Try NSFileManager's
- (NSArray *)contentsOfDirectoryAtPath:(NSString *)path error:(NSError **)error

Or, if your resources are in the app bundle, use -[NSBundle pathsForResourcesOfType:inDirectory:] as in
NSArray* mp3s=[[NSBundle mainBundle] pathsForResourcesOfType:#"mp3" inDirectory:nil];
Passing nil to the directory parameter defaults to the top level in the app bundle on iPhone, Resources/ in the OS X.

Related

writing NSMutable array to plist file via writeToFile

I have a plist file called playerData that includes a number object at index 0 indicating the highest level completed. After loading the view I read this object's integer value that is used throughout the game logic. If the player wins the game I would like to increment this number and write it to the plist file. here is the code I have (contained in an if statement)
levelNumber++;
NSNumber *levelNSNum = [[NSNumber alloc] initWithInteger:levelNumber];
[playerData replaceObjectAtIndex:0 withObject:levelNSNum];
[playerData writeToFile:[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:#"PlayerData.plist"] atomically:YES];
NSLog(#"%i should be written to file", levelNumber);
the log works so I know the conditions of the if statement have been met and the value is not the same as the one that was previously in the plist file, but for some reason this data is not being written over that data.
I am relatively new to this so I could be making an easy, stupid mistake I just can't seem to track down an answer. Thank you for your help!
You're trying to write to your bundle, which is read-only after the app is installed. You should write to somewhere in your app sandbox instead, such as in your Library/Application Support directory. (You can use - [NSFileManager URLsForDirectory:inDomains:] with NSApplicationSupportDirectory to find this path; be sure to create the directory before you try to write to it.)

Loading text from a file

I am making an Iphone drinking card game app.
All the card mean something different and i want the user to be able to press an info button and then show a new screen with information about the current card. How can i make a document to load text from instead of using a bunch og long strings?
Thanks
You could look into plist files - they can be loaded quite easily into the various collection objects and edited with the plist editor in Xcode.
For instance, if you organize your data as a dictionary, the convenience constructor
+ (id)dictionaryWithContentsOfURL:(NSURL *)aURL
from NSDictionary would provide you with as many easily accessible strings as you need.
This method is useful if you consider your strings primarily data as opposed to UI elements.
Update:
As #Alex Nichol suggested, here is how you can do it in practice:
To create a plist file:
In your Xcode project, for instance in the Supporting Files group, select New File > Resource > Property List
You can save the file in en.lproj, to aid in localization
In the Property list editing pane, select Add Row (or just hit return)
Enter a key name (for instance user1) and a value (for instance "Joe")
To read the contents:
NSURL *plistURL = [[NSBundle mainBundle] URLForResource:#"Property List" withExtension:#"plist"];
NSLog(#"URL: %#", plistURL);
NSDictionary *strings = [NSDictionary dictionaryWithContentsOfURL:plistURL];
NSString *user1 = [strings objectForKey:#"user1"];
NSLog(#"User 1: %#", user1);
A plist, a JSON string, and an SQLite database walked into a bar ...
Oops!! I mean those are the three most obvious alternatives. The JSON string is probably the easiest to create and "transport", though it's most practical to load the entire thing into an NSDictionary and/or NSArray, vs read from the file as each string is accessed.
The SQLite DB is the most general, and most speed/storage efficient for a very large number (thousands) of strings, but it takes some effort to set it up.
In my other answer, I suggest the use of a dictionary if your texts are mostly to be considered as data. However, if your strings are UI elements (alert texts, window titles, etc.) you might want to look into strings files and NSBundle's support for them.
Strings files are ideally suited for localization, the format is explained here.
To read them into you app, use something like this:
NSString *text1 = NSLocalizedStringFromTable(#"TEXT1", #"myStringsFile", #"Comment");
If you call your file Localizable.strings, you can even use a simpler form:
NSString *str1 = NSLocalizedString(#"String1", #"Comment on String1");
A useful discussion here - a bit old, but still useful.

How to get the file name in iPhone sdk?

I stored a pdf file using NSData in my application memory. Now i want that file name each time to add those names into an array. How can i get the pdf file's name from my application memory to use in my app.
You can't since you only stored the file as a data object and not it's file name.
You could try to read the PDF meta data to check if there's a file name.
The answer here should help:
Getting a list of files in the Resources folder - iOS
It will list all the files in the Documents dir.
I suppose by "Application Memory" you mean one of the App's directories like Documents or Library.
You can just use NSFileManager to access the directory and get a list of all files, like if you stored it in your app's library folder:
NSArray* directoryPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUSerDomainMask, YES];
NSString* path = [directoryPaths objectAtIndex:0];
NSArray* files = [NSFileManager defaultManager] contentsOfDirectoryAtPath:path];
On top of that you can use a filter predicate to only get files with a .pdf ending.

iPhone SDK: subFolders inside the main bundle

in the current project I have a number of folders, with subfolders, and these contain images: 01.png, 02.png.
Folder1/FolderA/f1.png
Folder1/FolderB/F1.png
When I compile the app, I looked inside the the .app and noticed that all the images are placed in the top level, with no sub-folders.
So clearly when trying to load the image this doesn't work:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"f1"
ofType:#"png"
inDirectory:#"Folder1/FolderA"];
But even more strangely, when loading image "f1", the image actually loads "F1"
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"f1.png"]];
Anyone have ideas on how to get around this problem?
Is there a compile option to create the folders in the app bundle?
TIA.
To create the subfolders inside the .app bundle, you should check the option "Create folder references for any added folders" rather than the default "Recursively create groups for any added folders"
Now in XCode, your imported folder appears blue rather than yellow. Build and go and you should see folders in your .app file.
First of all the folders you create in Xcode are simply organizational structures without any counterpart on the filesystem level. In other words all folders except for the "Classes" folder gets flatten out at the filesystem level. Therefore, even if you put your image file in the following location within xcode, it would still exist at the top-level in the filesystem: f1/f2/f3/f4/f5/image.png. Thus, in pathForResource method, you should not include the inDirectory argument.
As for the second issue, mac osx doesn't recognize case-sensitive file names. Therefore, f1 and F1 are equivalent to mac osx and will reference the same file. You can easily see this by executing the following 2 commands at a terminal session:
touch f
touch F
you'll notice that only 1 file exists after this: namely f. If you reverse the 2 commands, you still get one file, but it is named F.
ennuikiller is right. I think you can organize your images via Finder in subfolder and then refresh the image location in XCode by right clicking your image and selecting "Get Info" option. Then set the new directory.
Cheers.
Just wanted to add to Mugunth's answer, to follow up on part of the original question which was trying to use:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"f1" ofType:#"png" inDirectory:#"Folder1/FolderA"];
... to access files added using folder references. The above 'pathForResouce' call will work on simulators but not on actual iPhones (nil will be returned), because they don't seem to recognize subfolders in the 'inDirectory' part of the method. They do recognize them in the 'pathForResource' part, though. So the way of rephrasing the above so that it works on iPhones is:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"FolderA/f1" ofType:#"png" inDirectory:#"Folder1"];
I've followed your answer but it seams all files are stored flat on the root. If I use the code below to get the full path
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef url = CFBundleCopyResourceURL(mainBundle, CFSTR("About"), CFSTR("png"), NULL);
UInt8 filePath[PATH_MAX];
CFURLGetFileSystemRepresentation(url, true, filePath, sizeof(filePath));
I get as a result: /Users/iosif/Library/Application Support/iPhone Simulator/6.1/Applications/33FB4F79-999C-4455-A092-906A75226CDB/Arithmetics.app/About.png

Find all files in iphone project

I'm curious if there's a way to search for files in the iPhone's directory ( the location is irrelevant).
I am wanting to load in addresses from text files. The thing is additional files may be added and I want to dynamically be able to find the files and load in the data without hardcoding the file names to load in.
Thanks a bunch!
You want:
NSError *error;
[[NSFileManager defaultManager] contentsOfDirectoryAtPath:myPath error:&error]
It returns an array of NSString objects for each file in the given directory.