0

我有一个来自JSON提要的字典数组。这填充UITableView。当用户选择一行时,我使用UITableViewCellAccessoryCheckmark,并且我试图修改该行内数组中的字典,因此当滚动后再次使用该单元格时它保持正确。但是,我收到一个错误。这里是我的代码(简称为清楚起见):从UITableView中的行选择更新数组中的字典

JSON数据的方法:

+ (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; 
} 

视图控制器:

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]; 
} 

我得到一个SIGABRT错误:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object' 

我thoug我确信所有的东西都是可变的,所以我看不出它在哪里掉下来。

感谢

+1

你肯定** ** deserializeAsDictionary回报一个可变的字典? – 2012-03-08 17:57:06

回答

1

你说你确信你所有的东西不变,只是声明你*JSONDictionary*allResults*rowData指针是可变的,并不能让他们可变的。这些对象的可变性完全取决于作业的右侧。

从您收到的错误中可以明显看出,您试图在didSelectRowAtIndexPath:中编辑的字典是不可变的。另外,我对TouchJSON并不熟悉,但我很肯定allResults也是不可变的。

要纠正这个问题,您需要进行两项更改,在两种情况下都使用方便的mutableCopy方法来创建不可变数组或字典的可变副本。

NSMutableArray *allResults = [[JSONdictionary valueForKey:@"kennel"] mutableCopy]; 

,然后在tableView:didSelectRowAtIndexPath:,修改之前使字典的可变副本:首先,该阵列由parseKennelData:userID:dogID:terms:可变返回

NSMutableDictionary *rowData = [[self.results objectAtIndex:[indexPath row]] mutableCopy]; 
+0

您应该制作mutableCopy以确保它被复制到可变对象,例如:NSMutableArray * allResults = [JSONdictionary valueForKey:@“kennel”] mutablCopy]; – 2012-03-08 19:26:20

+0

这还不够:如果你这样做'self.results'将是一个不可变字典的可变数组。 – yuji 2012-03-08 19:30:52

+1

我看到了这一点,我只是展示了如何轻松制作不可变对象的可变副本作为示例。我不使用TouchJSON,所以我不能说数据是如何返回的。我应该说得更清楚。顺便说一句,iOS5有一个新的JSON API,这使得这个东西更容易。感谢上帝,这已经过时了。感谢您的澄清,我不想混淆任何人,这是与所有有关的东西相反。 – 2012-03-08 19:57:05