views:

337

answers:

2

Hello.

I am trying to edit a mutable array from a property and can't seem to directly make it work. Consider the following code that seems to work, but seems also very inefficient; I have to copy the whole property array just to make a change in one object. Why can I change the whole "carNames" array, but can't make a change to one of it's objects?

Thank you for any light you might be able to provide...

// CarTableViewController.h


// ...


@interface CarTableViewController : UITableViewController {
    NSMutableArray *carNames;
}

@property (nonatomic, retain) NSMutableArray *carNames;

-(IBAction)addCarButton:(id)sender;
// ...
// --------------------------------------

// -------CarTableViewController.m-------

// ...
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{

    if (editingStyle == UITableViewCellEditingStyleDelete) {

     // Could I somehow run the removeOjectAtIndex: 
     // directly on the carNames Property?  - this code works...

     NSMutableArray *mutablecarNames = [carNames mutableCopy];
     [mutablecarNames removeObjectAtIndex:indexPath.row];
     carNames = [mutablecarNames copy];
     [mutablecarNames release];

            // This code doesn't work... Why?
            // [carNames removeObjectAtIndex:indexPath.row];

    }

// ...
+7  A: 

You're setting carNames to be the result of [mutableCarNames copy], which is an immutable NSArray. You want mutableCopy instead.

Chuck
Thanks Chuck. I don't think I made myself clear. I would like to replace the four lines of code starting with "NSMutableArray ..." with a single line that edits the property directly. When I try to directly call [carNames removeObjectAtIndex:indexPath.row] the program crashes and says "...mutating method sent to immutable object." I don't understand why the carNames property is immutable when I declared it as mutable.
Michael
Sorry, I just noticed that my ID is showing as "unknown"... my name is Michael....
Michael
Yes, as I said, you need to make the object a mutable array.
Chuck
+1  A: 

Why are you not just calling [carNames removeObjectAtIndex:indexPath.row]?

That should work just fine, since it is a mutable array.

Kendall Helmstetter Gelner
That's what I thought, but it doesn't. It crashes and complains that I tried to send a mutating method to an immutable object...-Michael
Michael
Aha, then you must have created the carNames array using a non-mutable construction method - can we see that code?Or, perhaps you are changing the array somewhere else via copy...
Kendall Helmstetter Gelner
The carNames array is a property. The .h file is as follows (there's not much to it).---------------------------------------------------------#import <UIKit/UIKit.h>@interface CarTableViewController : UITableViewController { NSMutableArray *carNames;}@property (nonatomic, retain) NSMutableArray *carNames;-(IBAction)addCarButton:(id)sender;@end-----------------------------------------------------------------I initialize the carNames property array by using the following code.. tableviewcontroller.carNames = sortedCarNameList;where sortedCarNameList is a mutablearray.
Michael
sorry for the garbled code...I'll try to get the hang of this text editor...
Michael
Your "somewhere else" comment got me thinking... is the setter method using a copy statement? could I somehow create a custom setter method using mutable copy instead? If so, do you know what that code would look like?
Michael
Are you really, really sure sortedCarNameList is mutable? Because the fact is something is setting that array to a non-mutable value. There's no other explanation because mutable arrays do work. I would suggest setting a watch on the class variable to break whenever the value is changed (right click on class variable in Debugger window and select "watch variable")
Kendall Helmstetter Gelner
That helped track it down! I was initializing the sortedCarNameList with the flowing code....NSMutableArray *carNameList = [[NSMutableArray alloc] initWithContentsOfFile:fullPathFilename];NSMutableArray *sortedCarNameList = [carNameList sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];Apparently the sortedArrayUsingSelector was returning an immutable array which I was then setting to the carNames property. Thanks again!
Michael
Glad you got it solved, I thought the fact you were saying it was sorted was a little suspicious... I should have stated that explicitly since in other things I've done I sort first and then make a mutable copy.
Kendall Helmstetter Gelner