I would like to make my code a little better.
This is my array:
//All images - Add images to the queue
imagesQueue = [[NSMutableArray alloc] init];
[imagesQueue addObject:[UIImage imageNamed:#"climbing_001.jpg"]];
[imagesQueue addObject:[UIImage imageNamed:#"climbing_002.jpg"]];
[imagesQueue addObject:[UIImage imageNamed:#"climbing_003.jpg"]];
[imagesQueue addObject:[UIImage imageNamed:#"climbing_004.jpg"]];
All my images are inside an images folder in my resources.
Is there a way to automatically create an array from all the images in that folder?
NSBundle has a number of methods to help here. An example:
NSArray* imagePaths = [[NSBundle mainBundle] pathsForResourcesOfType:#"jpg" inDirectory:imagesFolder];
imagesQueue = [[NSMutableArray alloc] initWithCapacity:imagePaths.count];
for (NSString* path in imagePaths)
{
[imagesQueue addObject:[UIImage imageWithContentsOfFile:path]];
}
Use NSFileManager methods to discover the content of a directory.
Use NSBundle's resourcePath method to get this given path to the resources folder uour images are in, or directly the paths to those files using methods such as pathsForResourcesOfType:inDirectory:.
But I am not sure that base your code on the contents of your resources directory is the right approach. The best solution is probably to still setting the names of images in your code (instead of iterating into your folder contents), and set the images using a loop:
for(int i=0;i<4;++i) {
NSString* imageName = [NSString stringWithFormat:#"climbing_%03d.jpg",i+1];
[imagesQueue addObject:[UIImage imageNamed:imageName]];
}
Related
I have a folder with pictures in my project and i like to know how i could put this pictures from the folder into a array
How should i do that?
I tried this to put the images in the array
UIImage*image = [[NSBundle mainBundle]pathsForResourcesOfType:#"jpg" #"jpeg" #"gif" inDirectory:#"Images"];
NSArray*images = [[NSMutableArray alloc]initWithContentsOfFile:image];
You could do the following, getting the array of filenames and then filling another array with the images, themselves (assuming that's what you were trying to do).
NSMutableArray *imagePaths = [[NSMutableArray alloc] init];
NSMutableArray *images = [[NSMutableArray alloc] init];
NSArray *imageTypes = [NSArray arrayWithObjects:#"jpg", #"jpeg", #"gif", nil];
// load the imagePaths array
for (NSString *imageType in imageTypes)
{
NSArray *imagesOfParticularType = [[NSBundle mainBundle]pathsForResourcesOfType:imageType
inDirectory:#"Images"];
if (imagesOfParticularType)
[imagePaths addObjectsFromArray:imagesOfParticularType];
}
// load the images array
for (NSString *imagePath in imagePaths)
[images addObject:[UIImage imageWithContentsOfFile:imagePath]];
As an aside, unless these are tiny thumbnail images and you have very few, it generally would not be advisable to load all the images at once like this. Generally, because images can take up a lot of RAM, you would keep the array of filenames, but defer the loading of the images until you really need them.
If you don't successfully retrieve your images, there are two questions:
Are the files included in my bundle? When you select the "Build Phases" for your Target's settings and expand the "Copy Bundle Resources" (see the image below), do you see your images included? If you don't see your images in this list, they won't be included in the app when you build it. To add your images, click on the "+" and add them to this list.
Are the files in a "group" or in an actual subdirectory? When you add files to a project, you'll see the following dialog:
If you chose "Create folder references for added folders", then the folder will appear in blue in your project (see the blue icon next to my "db_images" folder in the preceding screen snapshot). If you chose "create groups for added folders", though, there will be the typical yellow icon next to your "Images" group. Bottom line, in this scenario, where you're looking for images in the subdirectory "Images", you want to use the "Create folder references for added folders" option with the resulting blue icon next to the images.
Bottom line, you need to ensure the images are in your app bundle and that they are where you think they are. Also note that iOS is case sensitive (though the simulator is not), so make sure you got the capitalization of "Images" right.
If I am understanding your question correctly initWithContentsOfFile doesn't do what you are expecting, per the documentation:
"Initializes a newly allocated array with the contents of the file specified by a given path."
Additionally, pathsForResourceOfType is already creating an array, not a UIImage, you can simply do:
NSArray* images = [[NSBundle mainBundle]pathsForResourcesOfType:#"jpg" #"jpeg" #"gif" inDirectory:#"Images"];
[[NSBundle mainBundle]pathsForResourcesOfType:#"jpg" #"jpeg" #"gif" inDirectory:#"Images"];
already returns an array of these objects. Change your line to this:
NSArray *images = [[NSBundle mainBundle]pathsForResourcesOfType:#"jpg" #"jpeg" #"gif" inDirectory:#"Images"];
Note that this array will only hold the paths for all your images. In order to make images of them you need to call
for(NSString* imagePath in images) {
UIImage* anImage = [[UIImage alloc] initWithContentsOfFile:imagePath];
//do something with your image here.
}
Hope that helps
Read the documentation of initWithContentsOfFile method of NSArray:
The array representation in the file identified by aPath must contain only property list objects (NSString, NSData, NSArray, or NSDictionary objects). The objects contained by this array are immutable, even if the array is mutable.
In your case you need to use NSFileManager to enumerate files in directory. Here is the example of directory enumeration from documentation:
NSFileManager *localFileManager=[[NSFileManager alloc] init];
NSDirectoryEnumerator *dirEnum =
[localFileManager enumeratorAtPath:docsDir];
NSString *file;
while (file = [dirEnum nextObject]) {
if ([[file pathExtension] isEqualToString: #"doc"]) {
// Create an image object here and add it to
// mutable array
}
}
[localFileManager release];
Try this:
NSMutableArray* paths=[NSMutableArray new];
NSFileManager* manager=[NSFileManager new];
NSBundle* bundle= [NSBundle mainBundle];
NSDirectoryEnumerator* enumerator= [manager enumeratorAtPath: [bundle bundlePath] ];
for(NSString* path in enumerator)
{
if([path hasSuffix: #".jpg"] || [path hasSuffix: #".jpeg"] || [path hasSuffix: #".gif"])
{
[paths addObject: path];
}
}
For explanations I suggest that you look at NSDirectoryEnumerator documentation.
Suppose, I have added one folder name "Images" in my project.How can I get the path to that folder? My main intention is to get the number of pictures in "Images" folder.
You should work a bit more on your question: it assumes a lot and requires the reader to guess.
I have added one folder name "Images" in my project
So I guess this means you added it as a folder reference
and I want to get it's path
And I guess that you want to do that at run time from your application, not at build-time from Xcode.
If so, you could do something like:
NSURL *containingURL = [[NSBundle mainBundle] resourceURL];
NSURL *imageURL = [containingURL URLByAppendingPathComponent:#"Images" isDirectory:YES];
NSFileManager *localFileManager = [[NSFileManager alloc] init];
NSArray *content = [localFileManager contentsOfDirectoryAtURL:imageURL includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsSubdirectoryDescendants error:NULL];
[localFileManager release];
NSUInteger imageCount = [content count];
This code does not assume that all images are of the same kind.
[[[NSBundle mainBundle] pathsForResourcesOfType:#"jpg" inDirectory:#"Images"] count];
This returns the number of jpg images from the Images folder. This is the case if you added the images to your application bundle.
I got annoying question...
What if I have many image , and I want load it in to a table view
And show the file name as cell's text , and the preview image is also show in the cell.
When I select the cell , it will push to next view , show the big size image.
That's it .
I don't know how to load many folder to an array?
/*********** EDIT ***********/
This is the folder I set many images inside
You can see that's only one root folder ...
And this is my code to load the image inside
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Image"ofType:#""];
NSDirectoryEnumerator *direnum;
direnum = [fileManager enumeratorAtPath: filePath];
imageFolder = [NSMutableArray new];
for(NSString *filename in direnum){
if([[filename pathExtension] isEqualToString:#"png"]){
[imageFolder addObject:filename];
}
}
NSLog(#"Files in the folder %#",imageFolder);
I got result like this :
Files in the folder (
"macro1.png",
"macro10.png",
"macro11.png",
"macro12.png",
"macro13.png",
"macro14.png",
"macro15.png",
"macro16.png",
"macro17.png",
"macro18.png",
"macro19.png",
"macro2.png",
"macro20.png",
"macro21.png",
"macro22.png",
"macro23.png",
"macro24.png",
"macro25.png",
"macro26.png",
"macro27.png",
"macro4.png",
"macro5.png",
"macro6.png",
"macro7.png",
"macro8.png",
"macro9.png"
)
But what if I change the root folder like this
How to read the image files in the subfolders?
The App won't have issues finding files inside the bundle. The structure of your app development folders is irrelevant to the end product, for the most part. If you are storing the images in the apps bundle, the system can find it.
UIImage *image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"imageName" ofType:#"png"]];
When I've had to do this as a quicky solution, I created an NSDictionary entry for each photo and stored that inside of an array in userPrefs. I programmatically created thumbnails for each image to utilize in the cell.imageView.image property, and then used an NSDictionary with #"description", #"imageName", and #"imageNameThumbnail" as the keys. You could do the same thing with an NSArray and just call the objectAtIndex, but I prefer the plain text friendliness of dictionaries.
You can try testing the path information that is being returned. Here are a couple of lines to try:
NSString *path1 = [[NSBundle mainBundle] pathForResource:#"imageName" ofType:#"png"];
NSString *path2 = [[NSBundle mainBundle] pathForResource:#"imageName" ofType:#"png" inDirectory:#"folderName"];
NSLog(#"Path 1: %#",path1);
NSLog(#"Path 2: %#",path2);
See what the output for these lines is, or if they return nothing.
Documents Directory as filePath
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
Then, enumerate the documentsDirectoryPath, and it should read subfolders recursively.
If it is local data you are using, you probably want to put the data in a .plist file. You would just be putting the names of the files in there, and then load the plist into an NSDictionary which you will only have one key for called "images" or something like that. You can then load all the objects under the "images" key into an array and use that array to populate your table.
Hope this makes sense.
I have problem with loading images from the Documents folder of iPhone application into the tableView.
In a separate request, I check on the server all the images available and download them into the "images" folder under Documents. I am pretty sure that the images are saved correctly.
NSString *filePath = [imagesFolderPath stringByAppendingPathComponent:imageFileName];
[urlData writeToFile:filePath atomically:NO];
NSLog(#"Saved to file: %#", filePath);
2010-01-22 17:07:27.307 Foo[2102:207] Saved to file: /Users/Hoang/Library/Application Support/iPhone Simulator/User/Applications/6133A161-F9DC-4C92-8AE6-5651022EAA94/Documents/images/86_2.png
[NSBundle mainBundle] is not suitable for loading the images because at runtime, the application tries to connect to the server to download the images, they are not static.
But loading the images from Documents/images folder does not give me the image on the TableView.
static NSString *CellIdentifier = #"CellCategory";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
UIImageView *imageView = cell.imageView;
MenuItem *item = (MenuItem *) [arrayMenuItems objectAtIndex:indexPath.row];
cell.textLabel.text = item.descrizione;
NSString *strImagePath = [[imagesFolderPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%d_%d", item.idItem, item.idNode]] stringByAppendingPathExtension:#"png"];
NSLog(#"strImagePath: %#", strImagePath);
imageView.image = [[UIImage imageWithContentsOfFile:strImagePath] autorelease];
2010-01-22 17:07:42.842 Foo[2102:207] strImagePath: /Users/Hoang/Library/Application Support/iPhone Simulator/User/Applications/6133A161-F9DC-4C92-8AE6-5651022EAA94/Documents/images/86_2.png
Is there anyone having the same problem?
I have looked around in stackoverflow but have not succeeded.
Thanks in advance.
I've just had the same problem with loading images from application's Documents folder to UITableViewCell. This works:
[UIImage imageWithContentsOfFile:fullPath];
hardcoding the path is a bad idea since it can change during a redeploy,
try something like this..
NSString *imagessDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/images"];
and verify the file/image is even there with nsfilemanager
Edited: ANSWER
Be sure to check the response on NSData to see if there are images. In my case, all codes are ok, but the response from server give nothing. It is still able to save the image to the file on the documents/images folder, and still not raise any error, until I realized that all the images are not exist on the server. THAT WAS THE ERROR, not relates anything to the Documents folder
Original answer
There must be some problems with the initialization code of UIImage.
I have tried already three initialization functions for image having the path on the Documents directory.
But it just does not work.
Here you can see, the code always fall into the (exist) block, the first line is to load the image from the Documents/images directory, it always fails.
The second line inside the (exist) block, I tried to get the image from the bundle, it works perfect, but it is not what I want.
Fourth line of code, I get the original link of the images on the server and it gets what I nearly want. (Actually, what I want is to save all the images from the server into the Documents/images directory before hand, and then load them from there)
NSString *strImagePath = [[imagesFolderPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%d_%d", item.idItem, item.idNode]] stringByAppendingPathExtension:#"png"];
NSLog(#"strImagePath: %#", strImagePath);
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:strImagePath];
if (exists){
//UIImage *menuImage = [UIImage imageWithContentsOfFile:strImagePath];
//UIImage *menuImage = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"ALT" ofType:#"png"]];
//imageView.image = menuImage;
NSString *strImagePathURL = [NSString stringWithFormat:#"http://foo.com/%d_%d.png", item.idItem, item.idNode];
NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:strImagePathURL]];
imageView.image = [[UIImage alloc] initWithData:imageData];
}
else {
imageView.image = [UIImage imageNamed:#"ALT.png"];
}
I'm trying to populate an NSArray with a collection of images in Resources. However, for maximum flexibility, I'm trying to avoid hard-coding the filenames or even how many files there are.
Normally, I'd do something like this example from the sample code at apple:
kNumImages = 5; //or whatever
NSMutableArray *images;
for (i = 1; i <= kNumImages; i++)
{
NSString *imageName = [NSString stringWithFormat:#"image%d.jpg", i];
[images addObject:[UIImage imageNamed:imageName];
}
However, I'm trying to avoid kNumImages entirely. Is there a way to run a regex or something on resources?
Here's a snippet that does just that from my iPhone app
// Load item icons
paths = [[NSBundle mainBundle] pathsForResourcesOfType:#"png" inDirectory:nil];
for (NSString *filename in paths) {
filename = [[filename componentsSeparatedByString:#"/"] lastObject];
if ([filename hasPrefix:#"ItemIcon"]) {
[UIImage imageNamed:filename];
}
}
It loops through all resources that have a png extension, and it the filename begins with "ItemIcon" then it loads into UIImage's built in cache.
If you have them in a specific directory, you will need to specify the indirectory: argument.