Unable to store an UIImage in an NSMutableArray - objective-c

I am trying to store a UIImage in an NSMutableArray but it doesn t work, here is the line I am using:
[images addObject:QRImage];
There are no compilation errors, but when I debug the app I see that the NSMutableArray has 0 objects. i.e. the image was not added.

I suspect your NSMutableArray is not properly initialized. Try this:
NSMutableArray *images = [[NSMutableArray alloc] init];
// ...
[images addObject:QRImage];

Related

EXC_BAD_ACCESS when I work with arrays

I always have error when working with arrays (non ARC code).
My code:
#implementation InfoController
NSMutableArray *lbCityArray;
NSMutableArray *lbTimeArray;
NSMutableArray *lbCameInArray;
NSMutableArray *lbCameOutArray;
NSMutableArray *lbInArray;
NSMutableArray *lbOutArray;
in ViewDidLoad I do something
- (void)viewDidLoad
{
[super viewDidLoad];
lbCityArray = [[NSMutableArray alloc] initWithCapacity:1];
lbTimeArray = [[NSMutableArray alloc] initWithCapacity:1];
lbCameInArray = [[NSMutableArray alloc] initWithCapacity:1];
lbCameOutArray = [[NSMutableArray alloc] initWithCapacity:1];
lbInArray = [[NSMutableArray alloc] initWithCapacity:1];
lbOutArray = [[NSMutableArray alloc] initWithCapacity:1];
//—add some values to arrays
NSString *City = #"London";
[lbCityArray addObject:City];
//—————————————-----------------------//
}
and always when I click Back button app crash with EXC_BAD_ACCESS. If I comment adding values to array all work, Back button don't crash app. I read if you use non ARC code you must manually release in dealloc.
I add to dealloc
[_InfoTableView release];
[lbCityArray release];
[lbTimeArray release];
[lbCameInArray release];
[lbCameOutArray release];
[lbInArray release];
[lbOutArray release];
[super dealloc];
and nothing changes, app still crash. Where can be problem ?
Solution - I move to ARC and all problems gone. Thanks.
It would help a lot if you made your variables into instance variables instead of global variables.
Change this:
#implementation InfoController
NSMutableArray *lbCityArray;
NSMutableArray *lbTimeArray;
NSMutableArray *lbCameInArray;
NSMutableArray *lbCameOutArray;
NSMutableArray *lbInArray;
NSMutableArray *lbOutArray;
into:
#implementation InfoController {
NSMutableArray *lbCityArray;
NSMutableArray *lbTimeArray;
NSMutableArray *lbCameInArray;
NSMutableArray *lbCameOutArray;
NSMutableArray *lbInArray;
NSMutableArray *lbOutArray;
}
Without the curly braces you are actually creating global variables, not instance variables.

FGallery issue on iPhone

I am trying to implement FGallery for displaying images in grid view. But i am facing one problem which i explained below:
When i try to load images with below method it works,
NSString *string1 = #"user/name/Library/ApplicationSupport/../Documents/image1.jpg";
NSArray *array = [[NSArray alloc]initWithObjects: string1,nil];
The above methods completely works withour error.
But When i try to load image with the below method i get only blank image,
NSString *string1 = (NSString *) [[self.allImagePath valueForKey#"image_Path"] objectAtIndex:0];
NSArray *array = [[NSArray alloc]initWithObjects: string1, nil];
The above method load blank images in both grid view and thumbnail view. Please guide me for solution.

NSMutableArray addObject in for loop - memory leak

i'm putting strings (which are filenames of files in a certain directory) into an NSMutableArray with a for loop:
h-file:
#import <Three20/Three20.h>
#interface AlbumController : TTThumbsViewController {
NSMutableArray *images;
}
#property (nonatomic, retain) NSMutableArray *images;
#end
m-file:
#import "AlbumController.h"
#import "PhotoSource.h"
#import "Photo.h"
#implementation AlbumController
#synthesize images;
-(void)createPhotos {
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:bundleRoot error:nil];
NSArray *onlyJPGs = [dirContents filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self ENDSWITH '.jpg'"]];
NSMutableArray *pics = [[onlyJPGs copy] autorelease];
if(!self.images) {
self.images = [[NSMutableArray alloc] init];
}
for(int i = 0; i < [onlyJPGs count]; i++)
{
//NSLog([pics objectAtIndex:i]);
NSString *ImgURL = [#"bundle://" stringByAppendingString:[pics objectAtIndex:i]];
Photo *photo = [[Photo alloc] initWithURL:ImgURL smallURL:ImgURL size:CGSizeMake(320, 212)];
[images addObject:photo];
[photo release];
}
}
-(void)viewDidLoad{
[self createPhotos]; // method to set up the photos array
self.photoSource = [[PhotoSource alloc]
initWithType:PhotoSourceNormal
title:#"Chili Pflanzen"
photos:images
photos2:nil
];
}
#end
i do not have any problem in the simulator but on my iPod...
Error message:
Data FOrmatters temporarily unavailable, will re-try after a 'continue'. (Unknown error loading shared library "/Developer/usr/lib/libXcodeDebuggerSupport.dylib")
thanks in advance
I think you should use mutableCopy and not copy on your pics array.
so instead of:
NSMutableArray *pics = [[onlyJPGs copy] autorelease];
you should use:
NSMutableArray *pics = [[onlyJPGs mutableCopy] autorelease];
More information about copy/mutablecopy in this question: Copy & mutableCopy?
Looks like the main issue is with
[images addObject:[[Photo alloc] initWithURL:ImgURL smallURL:ImgURL size:CGSizeMake(320, 212)]];
Here you are alloc'ing Photo but not releasing it. When you add an object to an array it increases the retain count for it.
Try changing it to
Photo *photo = [[Photo alloc] initWithURL:ImgURL smallURL:ImgURL size:CGSizeMake(320, 212)];
[images addObject:photo];
[photo release];
In addition ...
I'd change
self.images = [[[NSMutableArray alloc] init] autorelease];
to
if(!self.images) {
self.images = [[NSMutableArray alloc] init];
}
Otherwise there is the potential for a memory leak if it has already been initialized, as well as that you probably do not want it autoreleased;
Your NSMutableArray instance is autoreleased. You are assigning it to the images ivar. The fact that you have declared it as a retained property doesn't matter, because you aren't assigning it to the property. My guess is that you meant to assign to the property, and the crash is caused by the inadvertent deallocation.
Change:
images = [[[NSMutableArray alloc] init] autorelease];
...to:
self.images = [[[NSMutableArray alloc] init] autorelease];
...or:
images = [[NSMutableArray alloc] init];
Also note that your property is declared as NSArray when you are allocating an instance of NSMutableArray.
Also see the Memory Management Programming Guide.

EXC_BAD_ACCESS when returning UIImage

I have a method which should return a UIImage created from contentsOfFile (to avoid caching), but when it returns, i receive EXC_BAD_ACCESS. Running through Instruments doesn't reveal any results, as it just runs, without stopping on a zombie.
The image is correctly copied in the Bundle Resources phase...
- (UIImage *)imageForName:(NSString *)name {
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:#"png"];
return [UIImage imageWithContentsOfFile:path];
}
This method was adapted from the PhotoScroller sample, which works correctly.
Thanks
EDIT:
This is the code that uses imageForName, and you can see i added the retain, as per Luke/T's suggestion, but the EXC_BAD_ACCESS is on the return, not my addObject: call:
NSMutableArray *images;
for (NSDictionary *dict in imageListForPage){
[images addObject:[[self imageForName:[dict valueForKey:#"name"]]retain]];
}
ImageWithContentsOfFile will return an auto-released object. If you are not retaining it (on return [edit]) then you will get a bad access.
Edit:
Check the pointer of the NSarray. You need to init the Array either alloc as normal or use the arraywith
e.g.
NSMutableArray *images = [NSMutableArray arrayWithCapacity:ARRAY_CAPACITY];//autoreleased
or
NSMutableArray *images = [[NSMutableArray alloc] init];//release later
Adding an object to an NSMutableArray will implicitly send it a retain, so that's not necessary in your code.
Can you confirm (using NSLog() or a breakpoint) that
[UIImage imageWithContentsOfFile:path]
returns an object in your imageForName: method?
Finally, this code should be:
NSMutableArray *images = [NSMutableArray new]; // new is same as [[alloc] init]
for (NSDictionary *dict in imageListForPage) {
[images addObject:[self imageForName:[dict valueForKey:#"name"]]];
}
// ... do something with images
[images release];

Loading images into NSArray using initWithObjects crashes but not with an NSMutableArray?

I'm doing some lazy loading of images into an array when the app has loaded. I have tried using an NSMutableArray and an NSArray (I don't need to alter the array once it's been created) but the latter crashes on me.
...
[self performSelectorInBackground:#selector(loadImageArrays) withObject:nil];
...
- (void)loadImageArrays {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
NSString *fileName;
imageArray = [[NSMutableArray alloc] init];
for(int i = 0; i <= x; i++) {
fileName = [NSString stringWithFormat:#"image_0000%d.png", i];
[imageArray addObject:[UIImage imageNamed:fileName]];
}
[pool drain];
}
vs
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
imageArray = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"image_00000.png"],
[UIImage imageNamed:#"image_00001.png"],
[UIImage imageNamed:#"image_0000X.png"],
nil];
[pool drain];
NSZombieEnabled = YES tells me that [UIImage retain] was sent to deallocated instance when using the latter code-snippet.
Both arrays have (nonatomic, retain) property in my h-file. Why are the images not being retained by the NSArray?
UIImage is part of UIKit, which is not thread safe. For example, the method imageNamed: could corrupt the global name-image dictionary that the UIImage class uses for caching.
You have to use Core Graphics if you want to load images on a background thread.
Edit to answer your comment:
You can load PNG files with:
CGDataProviderRef source = CGDataProviderCreateWithURL((CFURLRef)url);
CGImageRef image = CGImageCreateWithPNGDataProvider(source, NULL, NO, kCGRenderingIntentDefault);
CFRelease(source);
A CGImage is a core foundation object and can be stored in an NSArray. You can then make a UIImage from it (on the main thread, of course):
[[UIImage alloc] initWithCGImage:image]
Although I know there is a big difference in mutable and immutable arrays, I'm in doubt myself. Something tells me this isn't purely a mutable vs immutable issue. Looks like your pool is drained prematurely (sounds nasty). Not that it should make a difference, but could you try to spawn a new thread by doing;
[NSThread detachNewThreadSelector:#selector(loadImageArrays) toTarget:self withObject:nil];
I'm simply curious of the result.. Also try both snippets in a clean environment (i.e: with no other code around). If your second code snippet works there, you should be looking elsewhere for the solution.