Brittany Brittany - 2 months ago 15
Objective-C Question

Error: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'

I'm attempting to allow my user to be able to delete/remove a row from a tableView (remove an object from an existing NSMutableArray), however when I try and delete the row, I get the following crash error:


Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: '-[__NSCFArray
removeObjectAtIndex:]: mutating method sent to immutable object'


Does anyone know why this might be? See code below. Apologies for the lengthy code.

.h

@property (strong, nonatomic) NSMutableArray *descripData;


.m

- (void)viewDidLoad {
[super viewDidLoad];

self.descripData = [[NSMutableArray alloc] init];

refreshControl = [[UIRefreshControl alloc]init];
[self.tableView addSubview:refreshControl];
[refreshControl addTarget:self action:@selector(refreshTable) forControlEvents:UIControlEventValueChanged];

NSMutableDictionary *viewParams = [NSMutableDictionary new];
[viewParams setValue:@"storeditems" forKey:@"view_name"];
[DIOSView viewGet:viewParams success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.descripData = responseObject;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Failure: %@", [error localizedDescription]);
}];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self.storageData count] > 0 && self.descripData.count > 0)
{
return [self.descripData count];
}
else
return 0;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *DoctorsTableIdentifier = @"StorageItemTableViewCell";

StorageItemTableViewCell *cell = (StorageItemTableViewCell *)[tableView dequeueReusableCellWithIdentifier:DoctorsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"StorageItemTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}

if (self.storageData.count > 0 && self.descripData.count > 0) {
noitemsView.hidden = YES;

NSDictionary *title = [self.descripData objectAtIndex:indexPath.row];
[[cell itemName] setText:[title objectForKey:@"node_title"]];

NSDictionary *node = [self.descripData objectAtIndex:indexPath.row];
[[cell itemDescrip] setText:[node objectForKey:@"body"]];
NSDictionary *value = [self.descripData objectAtIndex:indexPath.row];
[[cell valueLabel] setText:[value objectForKey:@"dollarvalue"]];
NSLog(@"%@", self.descripData);

NSDictionary *quantity = [self.descripData objectAtIndex:indexPath.row];
[[cell quantityLabel] setText:[quantity objectForKey:@"quantity"]];
NSLog(@"%@", self.descripData);

NSString *secondLink = [[self.descripData objectAtIndex:indexPath.row] objectForKey:@"photo"];

[cell.itemPhoto sd_setImageWithURL:[NSURL URLWithString:secondLink]];
}
else {
noitemsView.hidden = NO;
}
return cell;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 152;
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[self.descripData removeObjectAtIndex:indexPath.row];

[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView reloadData];
}
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ItemDetailViewController *detailViewController = [[ItemDetailViewController alloc] initWithNibName:@"ItemDetailViewController" bundle:nil];

detailViewController.itemDetail = [[values objectAtIndex:indexPath.row] objectForKey:@"node_title"];

detailViewController.itemDetail = [self.descripData objectAtIndex:indexPath.row];
detailViewController.secondLink = self.descripData[indexPath.row][@"photo"];

[self.navigationController pushViewController:detailViewController animated:YES];
}

Answer

Check the line self.descripData = responseObject;. It looks like you are probably setting your descripData property to point to a NSArray, not an NSMutableArray. If you really need the mutability, try self.descripData = [responseObject mutableCopy]; instead.