Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

talguy

macrumors member
Original poster
Jun 17, 2009
30
0
i seem to be getting a EXC_BAD_ACCESS error. I have enabled NSZombies to help me track where exactly I am getting the error. My program create a grid of images from the resources in my bundle. each image is a button that my error happen when I try to printout the name of each image that was read in from my plist and saved into a custom object on in an array. my array count is equal to the total amount read in but every object in the array is delocated. would I be accidentally delocating the objects in the array while I was building my grid view.

Code:
#import "Grid_ViewViewController.h"
#import "nextImageView.h"
#import "Grid_ViewAppDelegate.h"

@implementation Grid_ViewViewController
@synthesize myScrollView;


/*
 // The designated initializer. Override to perform setup that is required before the view is loaded.
 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
 if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
 // Custom initialization
 }
 return self;
 }
 */

/*
 // Implement loadView to create a view hierarchy programmatically, without using a nib.
 - (void)loadView {
 }
 */

- (void)viewDidLoad {
	[[Grid_ViewAppDelegate sharedAppDelegate] showLoadingView];
	self.title = @"Products";
    
    // Load property List data
    NSString *pathOfFile = [[NSBundle mainBundle] pathForResource:@"Products" ofType:@"plist"];
    NSData *plistData = [NSData dataWithContentsOfFile:pathOfFile];
    NSString *error;
    NSPropertyListFormat format;
    NSArray *plistArray = (NSArray*)[NSPropertyListSerialization propertyListFromData:plistData 
                                                                 mutabilityOption:NSPropertyListMutableContainers 
                                                                 format:&format
                                                                 errorDescription:&error];
    
    productArray = [[NSMutableArray alloc] initWithCapacity:[plistArray count]];
    
    if(plistArray) {
        Products *prod;
        for(NSDictionary *dict in plistArray) {
            prod = [[Products alloc] initWithDict:dict];
            [productArray addObject:prod];
            [prod release];
        }
    }
    // End load property list data
    
    [super viewDidLoad];
}


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidAppear:(BOOL)animated {
    
    int n = [productArray count];		// Numbers of items in array;
    
    myScrollView.contentSize = CGSizeMake(320, 460+n*2);	
    myScrollView.maximumZoomScale = 4;
    myScrollView.minimumZoomScale = 1;
    myScrollView.clipsToBounds = YES;
    myScrollView.delegate = self;
    
    int i=0, i1=0; 
    while(i < n) {
        int yy = 4 + i1 * 79; // compute next rows y pixel level
        for(int j=0; j<4; j++) {
            if(i >= n) 
                break;
            
            CGRect rect = CGRectMake(4+79*j, yy, 75, 75);
            UIButton *button = [[UIButton alloc] initWithFrame:rect];
            [button setFrame:rect];
            
            Products *prod = [productArray objectAtIndex:i];
            
            NSLog(@"Product Array item's name: %@",prod.ProductName);
            
            UIImage *buttonImageNormal = prod.ProductPic;
            
            
            [button setBackgroundImage:buttonImageNormal forState:UIControlStateNormal];
            button.tag = i; // button id representing an item in the array
            
            // Create button callback
            [button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
            
            [myScrollView addSubview:button];
            
            //[prod release];
            [button release];
            i++;
        }
        i1 = i1+1;
    }
    [[Grid_ViewAppDelegate sharedAppDelegate] hideLoadingView];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
}

- (void)dealloc {
    [super dealloc];
}

-(IBAction)buttonPressed:(id)sender {
	nextImageView *nextController = [[nextImageView alloc] initWithNibName:@"nextImageView" bundle:nil];
    
    Products *prod = [productArray objectAtIndex:[sender tag]];
    
    NSLog(@"Array Count: %d", [productArray count]);
    NSLog(@"Name: %@", prod.ProductName);  // PROBLEM IS HERE!!!!!!!!!
    
    [nextController changeImage:prod];
    
    [self.navigationController pushViewController:nextController animated:YES];
    [nextController release];
}

@end
 
I don't see anything wrong in that code at first glance. Maybe you could post your Products class?
 
here is the code to my product class

forgot to add before, the image grid displays fine and while in the viewdidappear method all the product names were printed out to the console correctly

Code:
#import <Foundation/Foundation.h>


@interface Products : NSObject {
    UIImage *ProductPic;
    NSString *ProductName;
    NSString *ProductManual;
}

@property (readonly, retain) UIImage *ProductPic;
@property (readonly, retain) NSString *ProductName;
@property (readonly, retain) NSString *ProductManual;

-(id)initWithDict:(NSDictionary*)dict;
@end

@implementation Products
@synthesize ProductPic;
@synthesize ProductName;
@synthesize ProductManual;

-(id)initWithDict:(NSDictionary*)dict {
    ProductName = [dict objectForKey:@"Name"];
    ProductManual = [dict objectForKey:@"Manual"];

    NSString *imageName = [[dict objectForKey:@"Image"] stringByReplacingOccurrencesOfString:@".gif" withString:@""];
    NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageName ofType:@"gif"];
    
    ProductPic = [[UIImage alloc] initWithContentsOfFile:imagePath];
    
    return self;
}
@end
 
ProductName and ProductManual are not being retained. objectForKey: returns an autoreleased object so those objects deallocate, and the pointer becomes garbage, so when you go to NSLog() the value, it crashes because the pointer no longer points to a valid object.

Since you declare these as properties, you should be consistent and access them as properties instead of the variable directly.

Try this:
Code:
self.ProductName = [dict objectForKey:@"Name"];
self.ProductManual = [dict objectForKey:@"Manual"];

Don't forget to implement dealloc in your class too, otherwise you're leaking all those objects.
 
that did not work. I have them as properties but they are readonly so you can't do self.(property name). I changed the property from readonly to nonatomic and readwrite and was still getting the same error.
 
haha yea. No every suggestion you can suggested I tried and was getting the same result. The code I am working with is the code posted at the top of the thread
 
here is the code to my product class

Code:
..snip..

-(id)initWithDict:(NSDictionary*)dict {
    ProductName = [dict objectForKey:@"Name"];
    ProductManual = [dict objectForKey:@"Manual"];

    NSString *imageName = [[dict objectForKey:@"Image"] stringByReplacingOccurrencesOfString:@".gif" withString:@""];
    NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageName ofType:@"gif"];
    
    ProductPic = [[UIImage alloc] initWithContentsOfFile:imagePath];
    
    return self;
}
@end

initWithDict: doesn't call [super init]. It isn't a proper init method.

And if you're still using the code posted at the top of the thread, then you still have bugs: the initial values assigned to ivars in initWithDict: are not being properly retained. And if you retain them, you must also have a dealloc that releases them.
 
thats because I tried them all and none of them worked so I reverted back to the original code
 
Just solved my problem. I was not retaining the picture, name or product manual in my product's init method. I also was not retaining the product object when inserting them into my array and was releasing them too early in the viewdidappear method.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.