EXC_BAD_ACCESS problem

Discussion in 'iOS Programming' started by talguy, Feb 10, 2010.

  1. talguy macrumors member

    Joined:
    Jun 17, 2009
    #1
    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
    
     
  2. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #2
    I don't see anything wrong in that code at first glance. Maybe you could post your Products class?
     
  3. talguy thread starter macrumors member

    Joined:
    Jun 17, 2009
    #3
    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
    
    
     
  4. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #4
    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.
     
  5. talguy thread starter macrumors member

    Joined:
    Jun 17, 2009
    #5
    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.
     
  6. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
  7. talguy thread starter macrumors member

    Joined:
    Jun 17, 2009
    #7
    did that no luck
     
  8. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
  9. talguy thread starter macrumors member

    Joined:
    Jun 17, 2009
  10. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #10
    What? You wiped it all out? ;)
     
  11. talguy thread starter macrumors member

    Joined:
    Jun 17, 2009
    #11
    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
     
  12. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #12
    But that code doesn't contain any of the suggested fixes (such as using the correct accessors for properties and making those properties nonatomic).
     
  13. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #13
    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.
     
  14. talguy thread starter macrumors member

    Joined:
    Jun 17, 2009
    #14
    thats because I tried them all and none of them worked so I reverted back to the original code
     
  15. talguy thread starter macrumors member

    Joined:
    Jun 17, 2009
    #15
    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.
     

Share This Page