I have an array of dictionaries from a JSON feed. This populates a UITableView
. When the user selects a row I use the UITableViewCellAccessoryCheckmark
, and I'm trying to modify the dictionary inside the array for that row, so when the cell is reused again after a scroll it stays correct. However I'm getting an error. Here's my code (shortened for clarity):
JSON data method:
+ (NSMutableArray *)parseKennelData:(NSString *)type userID:(NSString *)user dogID:(NSString *)dog terms:(NSString *)terms
{
NSURL *searchURL=[NSURL URLWithString:searchLocation];
// download and parse the JSON
NSData *JSONData = [[[NSData alloc] initWithContentsOfURL:searchURL] autorelease ];
NSError *error=nil;
CJSONDeserializer *deserializer = [CJSONDeserializer deserializer];
NSMutableDictionary *JSONdictionary =[deserializer deserializeAsDictionary:JSONData error:&error];
NSMutableArray *allResults = [JSONdictionary valueForKey:@"kennel"];
return allResults;
}
View Controller:
interface
{
NSMutableArray *results;
}
- (void)viewDidLoad
{
// data for search
self.results=[JSONData parseKennelData:@"search" userID:@"demo" dogID:@"" terms:self.terms];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableDictionary *rowData = [self.results objectAtIndex:[indexPath row]];
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if (thisCell.accessoryType == UITableViewCellAccessoryNone)
{
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
thisCell.accessoryView = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:@"tick-button.png"]];
[rowData setObject:@"demo" forKey:@"user_id" ];
}
else
{
thisCell.accessoryType = UITableViewCellAccessoryNone;
thisCell.accessoryView = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:@"plusbutton.png"]];
[rowData setObject:@"" forKey:@"user_id"];
}
[self.results replaceObjectAtIndex:[indexPath row] withObject:rowData];
}
I'm getting a SIGABRT error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
I thought I'd made sure all my stuff is mutable, so I can't see where it's falling over.
Thanks
You say you made sure all your stuff immutable, but just declaring your *JSONDictionary
, *allResults
, and *rowData
pointers to be mutable doesn't make them mutable. The mutability of those objects depends entirely on the right hand side of the assignment.
From the error you're getting, it's clear that the dictionaries you're trying to edit in didSelectRowAtIndexPath:
are immutable. Also, I'm not familiar with TouchJSON but I'm pretty sure allResults
is immutable too.
To rectify this, you need to make two changes, in both cases using the convenient mutableCopy
method to make a mutable copy of an immutable array or dictionary. First, make the array returned by parseKennelData:userID:dogID:terms:
mutable:
NSMutableArray *allResults = [[JSONdictionary valueForKey:@"kennel"] mutableCopy];
And then, in tableView:didSelectRowAtIndexPath:
, make a mutable copy of the dictionary before modifying it:
NSMutableDictionary *rowData = [[self.results objectAtIndex:[indexPath row]] mutableCopy];