views:

660

answers:

2

Been searching for the answer to this for a while now and I think due to the nature of my array set up, I may be searching for the wrong answer!

I have a class which handles adding items to my array:

// Item.h
@interface Item : NSObject {
    NSString *name;
    NSNumber *seconds;
}

@property(nonatomic,copy) NSString *name;
@property(nonatomic,copy) NSNumber *seconds;

- (id)initWithName:(NSString *)n seconds:(NSNumber *)sec;

@end

and...

//item.m

@implementation Item
@synthesize name, seconds;


- (id)initWithName:(NSString *)n seconds:(NSNumber *)sec {
    self.name = n;
    self.seconds = sec;
    return self;
}
@end

So to add an item, I use

Item *item1 = [[Item alloc] initWithName:@"runnerA" seconds:[NSNumber numberWithInt:780]];

I have some code which allows a user to edit a textfield (runner name) and the time which is a UIdatepicker set to hours and minutes. In the save method, that's working fine. It's the UPDATE that I cannot get to work. I've tried alsorts! Here's the code at the moment...

mainAppDelegate *appDelegate = (mainAppDelegate *)[[UIApplication sharedApplication] delegate];    
Item *item = [[Item alloc] initWithName:inputName.text seconds:[NSNumber numberWithInt:secs]];
[appDelegate.arrItems replaceObjectAtIndex:rowBeingEdited withObject:item];

The above is simply adding a new item to the array (which is what I don't want). I'm not sure how to replace values. At the function, I have the row I need to update (rowBeingEdited) and the fields inputName.text and secs are both OK. (NSLog out confirms this).

How do I use the replaceObjectAtIndex to actually replace it with the values?! It's driving me mad now!!

+1  A: 
  1. Are you using NSArray or NSMutableArray?
  2. Assuming you are using NSMutableArray, how did you initialize and populate the array in the first place?

For example, it's not enough to use -initWithCapacity: or +arrayWithCapacity: which only sets aside space. You have to use -addObject: for the first round of population, before you can use -replaceObjectAtIndex:withObject::

Note that NSArray objects are not like C arrays. That is, even though you specify a size when you create an array, the specified size is regarded as a “hint”; the actual size of the array is still 0. This means that you cannot insert an object at an index greater than the current count of an array. For example, if an array contains two objects, its size is 2, so you can add objects at indices 0, 1, or 2. Index 3 is illegal and out of bounds; if you try to add an object at index 3 (when the size of the array is 2), NSMutableArray raises an exception.

Alex Reynolds
Thanks for the reply... it's an NSMutableArray which is set up in the delegate file. When I add an item, I use [arrItems addObject:item];The array has been working nicely up to now, it populates and retrieves well.In the first instance, I useself.arrItems = [[NSMutableArray alloc] initWithObjects: nil];to set up the initial array. it's obviously empty there, so as the user adds in items it uses the addObject:item as above.
Matt Facer
Can you post code from your app delegate that describes your array, such as the property description and instantiation? Also, what happens when you try to replace an object at a pre-filled index? Does your application throw an exception? Does the array hold the previous object? Some NSLog output may also be helpful.
Alex Reynolds
+1  A: 

Since you are simply trying to edit a particular row, why not use those property accessors that you already have set up in Item? It would look something like this:

Item *item = (Item *)[appDelegate.arrItems objectAtIndex:rowBeingEdited];
[item setName:inputName.text];
[item setSeconds:[NSNumber numberWithInt:secs]];

An a side note, are you using garbage collection, or do you manually release the Item objects that you create when adding items to the array? If you are doing it manually, it should look like this:

Item *item1 = [[Item alloc] initWithName:@"runnerA"
                                 seconds:[NSNumber numberWithInt:780]];
[appDelegate.arrItems addObject:item1];
[item1 release];

This follows the rule of thumb: if you alloc, copy or retain anything, you must also release it. Note that this works because the array will retain the item when it is added.

e.James
cheers - this worked perfectly.I have only recently heard about garbage collection through searching for this solution. Is it something I should be using? and I have LOTS of uilabels, uibuttons etc which I set to nonatomic, retain but pretty sure I don't release. Does this have an affect on memory etc? Thanks again.
Matt Facer
When you declare a property `(nonatomic, retain)`, Cocoa takes care of the release for you. You only need to worry about releasing objects if you have written `[[SomeClass alloc] init...]` or `[someObject retain]` or `[someObject copy]`
e.James
As for garbage collection, I prefer not to use it, but it really comes down to personal choice. I would recommend reading up on Cocoa's memory management so that you can make an informed decision:http://developer.apple.com/iphone/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
e.James
Garbage collection is not available on the iPhone.
Alex Reynolds
@Alex Reynolds: Ah. Shows how much I know. Thank you for letting us know!
e.James