Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Nov 23, 2010, 10:55 PM   #1
isthisonetaken
macrumors regular
 
Join Date: Jun 2006
Adding temporary custom objects to NSMutableArray Problems

Hey All,

so I'm working on a little app, and for right now, to get the interface working correctly, I am adding some static objects to an NSMutableArray, but when that finishes, it adds the right number of objects, but they are all the same as the last object added.

Item is a custom object with this init method:
Code:
- (Item *)init {
	self = [super init];
	
	if (self) {
		category = @"";
		storeName = @"";
		storeAddress = @"";
		storeHours = @"";
		
		name = @"";
		quantity = 0;
		price = 0.0;
		description = @"";
		picture = @"";
		upc = 0;
	}
	
	return self;
}
Then, in a method in my AppDelegate, I build some tempItems:
Code:
Item *tempItem = [[Item alloc] init];
	// make a new item
	tempItem.category = @"Groceries";
        // all the other properties are set
[list addObject:tempItem];
        // same code for adding 3 more objects
If I have calls to NSLog before adding objects, it shows that tempObject is what I want it to be. When that is all done, I can see that list has 4 objects in it, but they are all the same as the last object added.

I feel like this is probably very easy to fix, but searching on Google, I couldn't find anything that worked. I tried releasing, and autoreleasing the tempObject after adding to the list and before changing it to the new object without success.

Any suggestions?

Dan
isthisonetaken is offline   0 Reply With Quote
Old Nov 23, 2010, 11:40 PM   #2
kainjow
Moderator emeritus
 
kainjow's Avatar
 
Join Date: Jun 2000
Post your complete code. If you're not alloc/initing your object after you add it to the array then you're simply modifying the same object over and over.
kainjow is offline   0 Reply With Quote
Old Nov 24, 2010, 02:24 AM   #3
lostp
macrumors newbie
 
Join Date: Nov 2010
Location: Bangalore, India
Send a message via Yahoo to lostp
NSMutableArray

I think he is setting the same objects over and over again. That means all the elements of the NSMutableArray *list point to the same memory location.

Try this code. Create new function to add to the list.

Code:
-(void) addNewItem: (NSString *)categ
{
     Item *tempName = [[Item alloc] init];
     //assuming category is a property defined as NSString 
     tempName.category = categ;
[list addObject:tempName];
}
in your AppDelegate.m just call -addNewItem on every object.

I hope this helps.
lostp is offline   0 Reply With Quote
Old Nov 24, 2010, 02:30 AM   #4
gnasher729
macrumors G5
 
gnasher729's Avatar
 
Join Date: Nov 2005
1. As you say yourself, the problem is not in the code that you posted. Post the code that contains the problem.

2. Turn compiler warnings on. Lots of problems will result in warnings from the compiler.
gnasher729 is offline   0 Reply With Quote
Old Nov 24, 2010, 08:39 AM   #5
whooleytoo
macrumors 603
 
whooleytoo's Avatar
 
Join Date: Aug 2002
Location: Cork, Ireland.
Send a message via AIM to whooleytoo
Quote:
Originally Posted by lostp View Post
I think he is setting the same objects over and over again. That means all the elements of the NSMutableArray *list point to the same memory location.

Try this code. Create new function to add to the list.

Code:
-(void) addNewItem: (NSString *)categ
{
     Item *tempName = [[Item alloc] init];
     //assuming category is a property defined as NSString 
     tempName.category = categ;
[list addObject:tempName];
}
in your AppDelegate.m just call -addNewItem on every object.

I hope this helps.
Note - you should probably release tempName in the method above; once you've added it to the array. Otherwise that's likely to leak.
__________________
Mac <- Macintosh <- McIntosh apples <- John McIntosh <- McIntosh surname <- "Mac an toshach" <- "Son of the Chief"
whooleytoo is offline   0 Reply With Quote
Old Nov 24, 2010, 08:45 AM   #6
whooleytoo
macrumors 603
 
whooleytoo's Avatar
 
Join Date: Aug 2002
Location: Cork, Ireland.
Send a message via AIM to whooleytoo
The most likely cause could be you're doing something like this:

Code:
Item* tempItem = [[Item alloc] init];

tempItem.category = @"Groceries";
[list addObject: tempItem];

tempItem.category = @"Bananas";
[list addObject: tempItem];
.
.
.
If you do that, you'll end up with 4 duplicate items in the array; since you're changing the original object each time.
__________________
Mac <- Macintosh <- McIntosh apples <- John McIntosh <- McIntosh surname <- "Mac an toshach" <- "Son of the Chief"
whooleytoo is offline   0 Reply With Quote
Old Nov 24, 2010, 09:18 AM   #7
lostp
macrumors newbie
 
Join Date: Nov 2010
Location: Bangalore, India
Send a message via Yahoo to lostp
Quote:
Originally Posted by whooleytoo View Post
Note - you should probably release tempName in the method above; once you've added it to the array. Otherwise that's likely to leak.
Oh yea also a [tempName release]; Thanks for correcting whooleytoo.
lostp is offline   0 Reply With Quote
Old Nov 24, 2010, 01:01 PM   #8
isthisonetaken
Thread Starter
macrumors regular
 
Join Date: Jun 2006
Code where I'm adding objects:
Code:
Item *tempItem = [[Item alloc] init];
	// make a new item
	tempItem.category = @"Groceries";
	tempItem.storeName = @"Loblaws";
	tempItem.storeAddress = @"1200 Richmond St East";
	tempItem.storeHours = @"9am-9pm";
	tempItem.name = @"milk";
	tempItem.quantity = 2;
	tempItem.price = 3.49;
	tempItem.description = @"2% milk in blue container";
	tempItem.picture = NULL;
	tempItem.upc = 123456;
	// add it to the list array
	//NSLog(@"tempItem 1 = %@\n", tempItem);
	[tempItem autorelease];
	[list addObject:tempItem];
//	NSLog(@"list count = %d",[list count]);
	// make a new item
	tempItem.category = @"Groceries";
	tempItem.storeName = @"Loblaws";
	tempItem.storeAddress = @"1200 Richmond St East";
	tempItem.storeHours = @"9am-9pm";
	tempItem.name = @"bread";
	tempItem.quantity = 1;
	tempItem.price = 1.99;
	tempItem.description = @"Whole Wheat bread, whatever is on sale.";
	tempItem.picture = NULL;
	tempItem.upc = 132657;
	// add it to the list array
	//	NSLog(@"tempItem 2 = %@\n", tempItem);

	[list addObject:tempItem];
//	NSLog(@"list count = %d",[list count]);

	// make a new item
	tempItem.category = @"Groceries";
	tempItem.storeName = @"Metro";
	tempItem.storeAddress = @"800 Oxford St West";
	tempItem.storeHours = @"24 Hours";
	tempItem.name = @"chicken";
	tempItem.quantity = 1;
	tempItem.price = 12.99;
	tempItem.description = @"Package of boneless, skinless chicken breasts.";
	tempItem.picture = NULL;
	tempItem.upc = 198712;
	// add it to the list array
	//	NSLog(@"tempItem 3 = %@\n", tempItem);

	[list addObject:tempItem];
//	NSLog(@"list count = %d",[list count]);

	// make a new item
	tempItem.category = @"Electronics";
	tempItem.storeName = @"Best Buy";
	tempItem.storeAddress = @"899 Wellington St N";
	tempItem.storeHours = @"9am-9pm";
	tempItem.name = @"iPad";
	tempItem.quantity = 1;
	tempItem.price = 549.00;
	tempItem.description = @"16 GB wifi iPad.";
	tempItem.picture = NULL;
	tempItem.upc = 817391;
	// add it to the list array
	//	NSLog(@"tempItem 4 = %@\n", tempItem);

	[list addObject:tempItem];
code for Item.m
Code:
#import "Item.h"


@implementation Item

@synthesize category;
@synthesize storeName;
@synthesize storeAddress;
@synthesize storeHours;

@synthesize name;
@synthesize quantity;
@synthesize price;
@synthesize description;
@synthesize picture;
@synthesize upc;

- (Item *)init {
	self = [super init];
	
	if (self) {
		category = @"";
		storeName = @"";
		storeAddress = @"";
		storeHours = @"";
		
		name = @"";
		quantity = 0;
		price = 0.0;
		description = @"";
		picture = @"";
		upc = 0;
	}
	
	return self;
}

@end
I tried putting [tempItem release]; after adding it to the list array, but that didn't help.
isthisonetaken is offline   0 Reply With Quote
Old Nov 24, 2010, 01:08 PM   #9
robbieduncan
Moderator
 
robbieduncan's Avatar
 
Join Date: Jul 2002
Location: London
As everyone suspected you are using the same item over and over. At the second point where it says "// make a new item" you have not made a new item at all. tempItem is still pointing at the item you created with alloc/init. You need to alloc/init each and every new item.
robbieduncan is offline   0 Reply With Quote
Old Nov 24, 2010, 01:23 PM   #10
lostp
macrumors newbie
 
Join Date: Nov 2010
Location: Bangalore, India
Send a message via Yahoo to lostp
Quote:
Originally Posted by isthisonetaken View Post
Code where I'm adding objects:
Code:
Item *tempItem = [[Item alloc] init];
	// make a new item
	tempItem.category = @"Groceries";
	tempItem.storeName = @"Loblaws";
	tempItem.storeAddress = @"1200 Richmond St East";
	tempItem.storeHours = @"9am-9pm";
	tempItem.name = @"milk";
	tempItem.quantity = 2;
	tempItem.price = 3.49;
	tempItem.description = @"2% milk in blue container";
	tempItem.picture = NULL;
	tempItem.upc = 123456;
	// add it to the list array
	//NSLog(@"tempItem 1 = %@\n", tempItem);
	[tempItem autorelease]; // edit by lostp WHY ARE YOU DOING THIS BEFORE ADDING IT TO LIST??
	[list addObject:tempItem];
//	NSLog(@"list count = %d",[list count]);
	// make a new item // << Where is the new item created? 
	tempItem.category = @"Groceries";
	tempItem.storeName = @"Loblaws";
	tempItem.storeAddress = @"1200 Richmond St East";
	tempItem.storeHours = @"9am-9pm";
	tempItem.name = @"bread";
	tempItem.quantity = 1;
	tempItem.price = 1.99;
	tempItem.description = @"Whole Wheat bread, whatever is on sale.";
	tempItem.picture = NULL;
	tempItem.upc = 132657;
	// add it to the list array
	//	NSLog(@"tempItem 2 = %@\n", tempItem);

	[list addObject:tempItem];
//	NSLog(@"list count = %d",[list count]);

	// make a new item << AGAIN. 
	tempItem.category = @"Groceries";
	tempItem.storeName = @"Metro";
	tempItem.storeAddress = @"800 Oxford St West";
	tempItem.storeHours = @"24 Hours";
	tempItem.name = @"chicken";
	tempItem.quantity = 1;
	tempItem.price = 12.99;
	tempItem.description = @"Package of boneless, skinless chicken breasts.";
	tempItem.picture = NULL;
	tempItem.upc = 198712;
	// add it to the list array
	//	NSLog(@"tempItem 3 = %@\n", tempItem);

	[list addObject:tempItem];
//	NSLog(@"list count = %d",[list count]);

	// make a new item
	tempItem.category = @"Electronics";
	tempItem.storeName = @"Best Buy";
	tempItem.storeAddress = @"899 Wellington St N";
	tempItem.storeHours = @"9am-9pm";
	tempItem.name = @"iPad";
	tempItem.quantity = 1;
	tempItem.price = 549.00;
	tempItem.description = @"16 GB wifi iPad.";
	tempItem.picture = NULL;
	tempItem.upc = 817391;
	// add it to the list array
	//	NSLog(@"tempItem 4 = %@\n", tempItem);

	[list addObject:tempItem];
code for Item.m
Code:
#import "Item.h"


@implementation Item

@synthesize category;
@synthesize storeName;
@synthesize storeAddress;
@synthesize storeHours;

@synthesize name;
@synthesize quantity;
@synthesize price;
@synthesize description;
@synthesize picture;
@synthesize upc;

- (Item *)init {
	self = [super init];
	
	if (self) {
		category = @"";
		storeName = @"";
		storeAddress = @"";
		storeHours = @"";
		
		name = @"";
		quantity = 0;
		price = 0.0;
		description = @"";
		picture = @"";
		upc = 0;
	}
	
	return self;
}

@end
I tried putting [tempItem release]; after adding it to the list array, but that didn't help.

Yes you're adding the same object over and over again.

first call
Code:
[tempItem release];
then call
Code:
tempItem = [[Item alloc] init];
to "create a new item". :-). Also read the comments posted above in CAPITAL letters. Sorry I wasn't shouting, I was just making a visual cue on which of them were my comments.
lostp is offline   0 Reply With Quote
Old Nov 24, 2010, 03:32 PM   #11
isthisonetaken
Thread Starter
macrumors regular
 
Join Date: Jun 2006
Ok guys thanks for the help, I've got it working now. And lostp, the autorelease was just something that was left in from trying things last night. Also, those comments about making a new item just meant changing the attributes, I didn't know I needed to alloc/ init each time!

Thanks again guys,

Dan
isthisonetaken is offline   0 Reply With Quote
Old Nov 24, 2010, 04:16 PM   #12
isthisonetaken
Thread Starter
macrumors regular
 
Join Date: Jun 2006
Ok, now I'm having another issue. On my interface, I have a popup button which I want to fill with Item.name and I have a textview which I want to fill with the category, store and item name for each item. The app itself has a NSMutableArray holding Items called list. I wrote two methods:

Code:
- (void)updateItemsPopup:(NSMutableArray *)items {
	// empty the popup than fill it with the names from items
	[itemListPopup removeAllItems];
	for (int i = 0; i < [items count]; i++) {
		[itemListPopup addItemWithTitle:[[items objectAtIndex:i] name]];
	}
	
	[self loadItemDetails:[items objectAtIndex:0]];
}
Code:
- (void)updateAllItemsView:(NSMutableArray *)items {
	NSString *content = @"";

	// build a string to go in the view
	for (int i = 0; i < [items count]; i++) {
		Item *tempItem = [[Item alloc] init];
		tempItem = [items objectAtIndex:i];
		content = [content stringByAppendingFormat:@"Category: %@ - Store: %@ - Item: %@\n", [tempItem category], [tempItem storeName], [tempItem name]];
		[tempItem release];
	}

	[allItemsView setString:content];
}
Then, after I build the Item objects and put them into list, I call those two methods:
Code:
[self updateAllItemsView:list];
		[self updateItemsPopup:list];
My problem is EXC_BAD_ACCESS. From putting in some breakpoints, it seems like by passing list to the first method, list gets deleted? If I only call one of those methods, then it will run fine (although, after checking, list is still being deleted).

I tried making a copy of list with:
Code:
NSMutableArray *listCopy = [[NSMutableArray alloc] initWithArray:list];
		[self updateAllItemsView:listCopy];
		[listCopy release];
		listCopy = [[NSMutableArray alloc] initWithArray:list];
		[self updateItemsPopup:listCopy];
		[listCopy release];
but that also seems to be deleting list.

I have declared list in my AppDelagate.h as:
Code:
@interface ShoppingAppDelegate : NSObject <NSApplicationDelegate> {
NSMutableArray *list;
}
@property (assign) NSMutableArray *list;
and synthesized it in the .m and initialize it:
Code:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
	// Insert code here to initialize your application 
	// initialize the list array
	list = [[NSMutableArray alloc] initWithCapacity:5];
}
I don't see why it is getting deleted whenever I try to do something other than add an object or remove an object?

Dan
isthisonetaken is offline   0 Reply With Quote
Old Nov 24, 2010, 04:42 PM   #13
lee1210
macrumors 68040
 
lee1210's Avatar
 
Join Date: Jan 2005
Location: Dallas, TX
I haven't run the code, but from a quick perusal it's clear that you need to read (or re-read) the memory management guide. You're leaking and over-releasing all over the place.

-Lee

Edit: what do you mean by "delete"? The list is empty? The pointer is nil? All of the items are invalid?
lee1210 is offline   0 Reply With Quote
Old Nov 24, 2010, 05:02 PM   #14
isthisonetaken
Thread Starter
macrumors regular
 
Join Date: Jun 2006
By deleting, I mean when I go in the debugger, before either of the method calls, I can see list, after one of the method calls, its gone. I know I need to read the memory management guide, I'm assuming I can find that in the developer site? I have garbage collection turned on, the one cocoa book I followed never went over memory management because it always had you turn on the garbage collection.

Where do you see the leaks? I'm guessing you mean where I tried making a copy of list? If so, I don't have that any more, I was just trying it out.

Dan
isthisonetaken is offline   0 Reply With Quote
Old Nov 24, 2010, 06:19 PM   #15
whooleytoo
macrumors 603
 
whooleytoo's Avatar
 
Join Date: Aug 2002
Location: Cork, Ireland.
Send a message via AIM to whooleytoo
A few problems there!

Look at the following code in updateAllItemsView:

Code:
Item *tempItem = [[Item alloc] init];
tempItem = [items objectAtIndex:i];
content = [content stringByAppendingFormat:@"Category: %@ - Store: %@ - Item: %@\n", [tempItem category], [tempItem storeName], [tempItem name]];		
[tempItem release];
- You create a new Item, pointed to by tempItem. This is fine.
- You then point tempItem at a different item from the items array. This is bad. The Item you created in the first line has just been leaked!
- Finally, you release the item tempItem points to. Since tempItem points to an Item in the items array, this line is now actually releasing the item in the array!

The following would be better:

Code:
Item *tempItem = [items objectAtIndex:i];
content = [content stringByAppendingFormat:@"Category: %@ - Store: %@ - Item: %@\n", [tempItem category], [tempItem storeName], [tempItem name]];
- You don't need to 'alloc' a a new Item. The Item already exists; it's in the items array.
- Since you don't alloc it, you don't need to release it either. Easy peasy.
__________________
Mac <- Macintosh <- McIntosh apples <- John McIntosh <- McIntosh surname <- "Mac an toshach" <- "Son of the Chief"
whooleytoo is offline   0 Reply With Quote
Old Nov 24, 2010, 07:18 PM   #16
lee1210
macrumors 68040
 
lee1210's Avatar
 
Join Date: Jan 2005
Location: Dallas, TX
Quote:
Originally Posted by isthisonetaken View Post
By deleting, I mean when I go in the debugger, before either of the method calls, I can see list, after one of the method calls, its gone. I know I need to read the memory management guide, I'm assuming I can find that in the developer site? I have garbage collection turned on, the one cocoa book I followed never went over memory management because it always had you turn on the garbage collection.

Where do you see the leaks? I'm guessing you mean where I tried making a copy of list? If so, I don't have that any more, I was just trying it out.

Dan
I still am not sure what you mean by "it's gone" here. When you print with the debugger the pointer is 0/nil? The length is 0? Something else? The variable itself can't disappear.

Also, if you have GC on none of the retain/release stuff should matter. As such, this shouldn't be the problem. With that said, I still think memory management is important to understand.

-Lee

Edit:
http://www.google.com/m/url?client=s...c0CHTxDRchKZrA
There's the memory management guide.

Whooleytoo pointed out where you were leaking and over-releasing, but with GC that should not be an issue.

Last edited by lee1210; Nov 24, 2010 at 07:25 PM.
lee1210 is offline   0 Reply With Quote
Old Nov 24, 2010, 08:34 PM   #17
isthisonetaken
Thread Starter
macrumors regular
 
Join Date: Jun 2006
Well now I feel dumb. Turns out when I said I had garbage collection enabled, it was enabled on an older version of this project. Its on now though. Also, before turning it on, whooleytoo's suggestions did the trick!

As for it being gone, if I had a breakpoint set just before calling updateAllItemsView, in the debugger, I could see the list array. After going through the method, it was gone, but that might be due to the program having the EXC_BAD_ACCESS?

Thanks for all the help guys!

Dan
isthisonetaken is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
Adding a Custom Phone Label when adding or Editing contacts Chris Kavanagh iOS 7 0 Oct 20, 2013 04:28 PM
OpenGL ES: Vertex Buffer Objects and Vertex Array Objects Blakeasd iPhone/iPad Programming 2 Jul 12, 2013 11:24 PM
Problems after adding SSD Borman Mac Pro 6 Feb 3, 2013 10:49 PM
Adding a custom ring tone GIZBUG iPhone 0 Oct 17, 2012 10:26 AM
Adding/Modifying custom words programatically to iOS dictionary from a csv file ashwinr87 iPhone/iPad Programming 1 Sep 27, 2012 11:38 AM

Forum Jump

All times are GMT -5. The time now is 12:48 AM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC