How to separate images out from Resources in iOS - ios

I'm displaying a set of images in my app. I've got the code working when I load the image from the Resources folder, like so:
- (void)viewDidLoad
{
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:[NSString stringWithFormat: #"pic_a"]];
[array addObject:[NSString stringWithFormat: #"pic_b"]];
[array addObject:[NSString stringWithFormat: #"pic_c"]];
[array addObject:[NSString stringWithFormat: #"pic_d"]];
int index = arc4random() % [array count];
NSString *pictureName = [array objectAtIndex:index];
NSString* imagePath = [ [ NSBundle mainBundle] pathForResource:pictureName ofType:#"png"];
UIImage *img = [ UIImage imageWithContentsOfFile: imagePath];
if (img != nil) { // Image was loaded successfully.
[imageView setImage:img];
[imageView setUserInteractionEnabled:NO];
[img release]; // Release the image now that we have a UIImageView that contains it.
}
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
However, if I create an "images" group within the "Resources" group, and put try to load the images from there, the image within the view shows up blank.
[array addObject:[NSString stringWithFormat: #"images/pic_a"]];
[array addObject:[NSString stringWithFormat: #"images/pic_b"]];
[array addObject:[NSString stringWithFormat: #"images/pic_c"]];
[array addObject:[NSString stringWithFormat: #"images/pic_d"]];
I'd like to separate the images out from the nib files and all the other cruft. What's the best way to do that?

Even if you have the images in a separate group within Resources, you can load them by calling the name, e.g. use this one line
UIImage *img = [UIImage imageNamed:[array objectAtIndex:index]];
in place of these three lines:
NSString *pictureName = [array objectAtIndex:index];
NSString* imagePath = [ [ NSBundle mainBundle] pathForResource:pictureName ofType:#"png"];
UIImage *img = [ UIImage imageWithContentsOfFile: imagePath];
You will still fill the array simply by
[array addObject:[NSString stringWithFormat: #"pic_a"]];
If you have both jpg and png files, then you should append .png to the end of the file names. Otherwise, leaving it off is fine.

Try using the imageNamed: method instead of imageWithContentsOfFile:

You need to create a physical folder called images (it should have a blue color instead of the usual yellow color)

Remember that adding groups inside your project it is simply for organization and look within Xcode. You adding a group will not change the fact that the images will be saved in the main bundle. If you are trying to find them using the images group in the string it will not find them.
There are some things you can do to make this work, but in reality you don't need to.

Related

Receiveing array of Images from CoreData

I've created NSManagedObject* imagesArrayData that stores strings (paths) to images stored in the documents directory:
- (void)setImagesArray:(NSMutableArray *)imagesArray {
NSMutableArray* newImagesArray = [NSMutableArray new];
int i = 1;
for (UIImage* image in imagesArray) {
//generate path to createdFile
NSString* fileName = [NSString stringWithFormat:#"%#_%d", self.name, i];
NSString* filePath = [self documentsPathForFileName:fileName];
//save image to disk
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:filePath atomically:YES];
//add image path to CoreData
[newImagesArray addObject:filePath];
i++;
}
//set new value of imagesArray
imagesArrayData = [NSKeyedArchiver archivedDataWithRootObject:newImagesArray];
I am now not showing pathsToImages in header file, but property imagesArray:
-(NSMutableArray*) imagesArray {
NSMutableArray* images = [NSMutableArray new];
NSArray* imagePaths = [NSKeyedUnarchiver unarchiveObjectWithData:imagesArrayData];
for (NSString* imagePath in imagePaths) {
UIImage *image = [[UIImage alloc] initWithContentsOfFile: imagePath];
[images addObject:image];
}
return images;
The problem is, that whenever I want to get to [imagesArray objectatIndex:xxx], the imagesArray getter is called, and it takes time to recreate the full array. When trying to switch fast between images, the UI slows down.
What would be the elegant way to overcome this problem? Maybe creating another array full of images and updating it from time to time? Maybe something else? Please, help.
One thing you could do is refactor your getter to lazily load the array. If it is already defined, simply return it. If not, build it:
-(NSMutableArray*) imagesArray
{
if (!_imagesArray)
{
NSMutableArray* _imagesArray = [NSMutableArray new];
NSArray* imagePaths =
[NSKeyedUnarchiver unarchiveObjectWithData: imagesArrayData];
for (NSString* imagePath in imagePaths)
{
UIImage *image = [[UIImage alloc] initWithContentsOfFile: imagePath];
[_imagesArray addObject:image];
}
return _imagesArray;
}
I'm not sure what you mean about updating an array of images from time to time.
If your array of image names changes you will need some method to respond to those changes.

Adding list of URLs to an array?

I'm using MHVideoPhotoGallery to create gallery's of images that are stored on my website. The current way to add images (as shown in the example on Github) is
MHGalleryItem *photo1 = [MHGalleryItem.alloc initWithURL:#"*ENTER IMAGE URL HERE*"
galleryType:MHGalleryTypeImage];
MHGalleryItem *photo2 = [MHGalleryItem.alloc initWithURL:#"*ENTER IMAGE URL HERE*"
galleryType:MHGalleryTypeImage];
MHGalleryItem *photo3 = [MHGalleryItem.alloc initWithURL:#"*ENTER IMAGE URL HERE*"
galleryType:MHGalleryTypeImage];
self.galleryDataSource = #[#[photo1,photo2,photo3]];
But I want to add hundreds of images and this is not the most ideal way to do it. What would be an easier way for me to accomplish this?
Thanks!
You have to start with a list of the URLs. What I would do is put this in a text file in my bundle. In code, when the app runs, I would open the text file (as an NSString) and split it into an NSArray. Now I've got an NSArray of the URLs. I would then cycle through the NSArray. So now we're inside a loop. For each item the array, I would initialize the MHGalleryItem and then add it to a previously created NSMutableArray with addObject:. Thus we have a two or three-line loop which is repeated, running through all the URLs.
The following is pseudo-code and untested (so it might contain errors), but it should give the general idea of the structure I'm suggesting:
NSMutableArray* temp = [NSMutableArray new];
NSString* s =
[NSString stringWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"urls" ofType:#"txt"]
encoding:NSUTF8StringEncoding error:nil];
NSArray* urls = [s componentsSeparatedByString:#"\n"];
for (NSString* url in urls) {
MHGalleryItem *item = [[MHGalleryItem alloc] initWithURL:url
galleryType:MHGalleryTypeImage];
[temp addObject:item];
}
self.galleryDataSource = temp;
Loop. If you're putting numbers at the end of your variable names, you need a loop and/or an array.
NSMutableArray * photos = [NSMutableArray new];
NSArray * photoPaths = [NSArray arrayWithContentsOfFile:plistContainingPhotoPaths];
for( NSString * path in photoPaths ){
NSURL * photoURL = [NSURL URLWithString:path];
MHGalleryItem * photo = [[MHGalleryItem alloc] initWithURL:photoURL
galleryType:MHGalleryTypeImage];
[photos addObject:photo];
}
And don't use dot syntax for alloc, or your code will burst into flames.
Use a naming protocol on your website such as:
www.mywebsite.com/appImageGallery/insertImageNumber
And replace the insertImageNumber with the number of you image. Then add this for loop to get all of the images and add them to the array.
NSMutableArray *mutableGalleryDataSource = [self.galleryDataSource mutableCopy]
for(int i = 0; i < numberOfImagesOnWebsite; i++){ //replace numberOfImagesOnWebsite with the number of images on your website.
MHGalleryItem *newItem = [MHGalleryItem.alloc initWithURL:[#"www.mywebsite.com/appImageGallery/" stringByAppendingString:[NSString stringWithFormat: #"%i", i]] galleryType:MHGalleryTypeImage];
[mutableGalleryDataSource addObject:newItem];
}
self.galleryDataSource = mutableGalleryDataSource;
There is also an -addObjectsFromArray method on NSMutableArray.

Load images from a documents subdirectory into UICollectionViewCell

I have several images in png format in "/Documents/saved/" directory.
I loaded this directory into an array called "contents"
When i use NSLog to view the contents of this array, i see the images as well as a .DS_STORE file
What i want to do is load all these images into UICollectionView cells.
I tried this,
[[cell collectionImageView] setImage:
[UIImage imageWithContentsOfFile:
[contents objectAtIndex:indexPath.item]]];
The collectionImageView is connected to the UIImageView in the UICollectionViewCell
But it doesn't seem to work.EDIT
NSString *dataPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/DImage"];
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dataPath error:NULL];
NSLog(#"%#", contents);
This gives me the output
2013-03-25 10:37:20.186 aUX[543:c07] (
".DS_Store",
"savedImage_0.png",
"savedImage_1.png",
"savedImage_2.png",
"savedImage_3.png",
"savedImage_4.png",
"savedImage_5.png"
)
(I have dragged a UIImageView named collectionImageView.)
I need to display these images one by one in the collection view cells.
It is not clear what data types you are using. Maybe breaking up your one-liner might help bring more clarity to the situation. Also, in this way you can check each step with NSLog or in the debugger.
NSString *fileName = [contents objectAtIndex:indexPath.item];
NSString *path = [filesDirectory stringByAppendingPathComponent:fileName];
UIImage *image = [UIImage imageWithContentsOfFile:path];
UIImageView *cellImageView = cell.collectionImageView;
cellImageView.image = image;
Maybe your contents array contains NSURLs rather than NSStrings. In this way you can find out.
in ur cellForRowAtIndexPath
cell.collectionImage.image=[contents objectAtIndex:indexPath.row];
return cell;

NSmutablearray adding unknown amount of images

I have an array i'm filling with images with a loop
items = [[NSMutableArray alloc] init];
for (int i=0; i<43; i++) {
NSString *filepath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%d",i] ofType:#"png"];
UIImage *image = (UIImage*)[UIImage imageWithContentsOfFile:filepath];
[items addObject:image];
}
it works as long as I set the max amount to match my test images. (in this case 43) if I set the max to a higher number, say 200 it of course crashes cause its trying to add nil objects to the array.
How would I go about being able to add the random number of images with that naming scheme to that array?
I have heard mention of using NSFileManager to add the files to array, is that the better method?

Only some png images display, others don't for no apparent reason

I have some code which randomly displays a given .png image and its title.The title logic is working fine. However, for some reason, only two of the four images display. I've tried changing the order just in case, but only those two images, pic_c and pic_d, ever get displayed. I've also checked the spelling, and that the files are in resources and exist on the file system. Here's the code which displays the image:
NSMutableArray *fileNameArray = [[NSMutableArray alloc] init];
[fileNameArray addObject:[NSString stringWithFormat: #"pic_a"]];
[fileNameArray addObject:[NSString stringWithFormat: #"pic_b"]];
[fileNameArray addObject:[NSString stringWithFormat: #"pic_c"]];
[fileNameArray addObject:[NSString stringWithFormat: #"pic_d"]];
NSMutableArray *titleArray = [[NSMutableArray alloc] init];
[titleArray addObject:[NSString stringWithFormat: #"pic a"]];
[titleArray addObject:[NSString stringWithFormat: #"pic b"]];
[titleArray addObject:[NSString stringWithFormat: #"pic c"]];
[titleArray addObject:[NSString stringWithFormat: #"pic d"]];
int index = arc4random() % [fileNameArray count];
NSString *pictureName = [titleArray objectAtIndex:index];
art_title.text = pictureName;
NSString* imagePath = [ [ NSBundle mainBundle] pathForResource:pictureName ofType:#"png"];
UIImage *img = [ UIImage imageWithContentsOfFile: imagePath];
if (img != nil) { // Image was loaded successfully.
[imageView setImage:img];
[imageView setUserInteractionEnabled:NO];
[img release]; // Release the image now that we have a UIImageView that contains it.
}
[super viewDidLoad];
[fileNameArray release];
[titleArray release];
}
Any idea why this might be happening?
Recent information: If I remove the titleArray, and use the file name array only, all the images show up. However, I'd still like to be able to use the titleArray.
What are your image files actually called? In the code above you don't actually do anything with finleNameArray except count it. You use the values from titleArray to get the image resource. I would think you need the following code in there:
NSString *filename = [fileNameArray objectAtIndex:index];
Then change your imagePath to use this instead of pictureName.

Resources