更新/更改存储在 NSArray 中的 NSDictionary 键的值

Posted

技术标签:

【中文标题】更新/更改存储在 NSArray 中的 NSDictionary 键的值【英文标题】:Update/change values of NSDictionary keys stored in NSArray 【发布时间】:2015-01-27 14:36:11 【问题描述】:

我有一个 NSArray 包含 NSDictionary 的客户端数据。我正在使用NSPredicate 过滤array 并将其通过ViewControllerssegues。我正处于想要更改存储在dictionary 中的键的一些值的阶段。这是如何实现的?

我的prepareForSegue 方法

if ([[segue identifier] isEqualToString:@"showClients"]) 
            // Detect selected row
            NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
            // Extract value from the Clinic_Location attribute
            NSString *cString = [[_clinicList valueForKey:@"Clinic_Location"] objectAtIndex:indexPath.row];
            NSLog(@"Row pressed: %@", cString);

            // Set predicate where Clinic_Location equals the clinic string extracted from the selected row
            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Clinic_Location == %@", cString];
            // Filter the client array using this predicate
            filteredClientArray = [dataStart filteredArrayUsingPredicate:predicate];
            NSLog(@"Filtered array: %@", filteredClientArray);
            // Reload the table
            [self.tableView reloadData];

            // Sort the array by Appt_Time in ascending order
            NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"Appt_Time" ascending:YES];
            NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
            NSArray *sortedArray = [filteredClientArray sortedArrayUsingDescriptors:sortDescriptors];
            filteredClientArray = [NSMutableArray arrayWithArray:sortedArray];

            // Pass the newly filtered & sorted array to next view
            PCClientsViewController *pcClients = segue.destinationViewController;
            pcClients.clientArray = filteredClientArray;
        

array 现在只包含基于此predicate 的某些dictionaries(即,当用户在TableView 上选择一行时,假设'Manchester',那么只有dictionariesClinic_Location Manchester 被传递到下一个视图。

我在下一个TableView 上的prepareForSegue 方法与前一个方法类似,在这种情况下,我的predicate 在所选行上过滤dictionary 并带有匹配的姓氏,并将其推送到下一个视图。现在我剩下一个array,如下所示:

Filtered array: (
        
        "Appointment_Attended" = Yes;
        "Appt_Time" = "2:00";
        "Client_Address_Line_1" = "Ap #452-4253 Massa. Street";
        "Client_Address_Line_2" = Montebello;
        "Client_Address_Line_3" = Hull;
        "Client_Address_Line_4" = Quebec;
        "Client_Address_Line_5" = Micronesia;
        "Client_Forename" = Veronica;
        "Client_Postcode" = 69591;
        "Client_Surname" = Ellis;
        "Client_Tel" = "(019376) 26081";
        "Clinic_Location" = Manchester;
        "Passed_To_Medical" = No;
        "Passed_To_Sol" = No;
    
)

我尝试了许多不同的方法来更新此array 中的特定dictionary keys,例如使用predicates,但似乎没有任何效果。例如:

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"Client_Address_Line_1 == %@", [[_clientDetails valueForKey:@"Client_Address_Line_1"]objectAtIndex:0]];
NSLog(@"%@", predicate);
NSArray* filteredArray= [_clientDetails filteredArrayUsingPredicate: predicate];
[filteredArray performSelector: @selector(setValue:forKey:) withObject:self.clientAddLine1.text withObject:@"Client_Address_Line_1"];

无论我尝试什么,我都会不断收到错误消息,例如:

*** 由于未捕获的异常“NSUnknownKeyException”而终止应用程序,原因:“[<__nscfstring> setValue:forUndefinedKey:]: this 类与键的键值编码不兼容 Client_Address_Line_1。'

*** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[__NSDictionaryI setObject:forKey:]: 无法识别的选择器发送到实例 0x78774c70'

*** 由于未捕获的异常“NSUnknownKeyException”而终止应用程序,原因:“[<__nsdictionaryi> setValue:forUndefinedKey:]: 此类与键的键值编码不兼容 Client_Address_Line_1。'

似乎无论我做什么,我都无法更改或更新array 中的任何dictionary keys。经过数小时的研究,我开始怀疑这是否可能?我是否完全看错了方法?有一个更好的方法吗?更改 keys 后,我需要将它们保存回 array 并通过 ViewControllers 将其传递回(可能与 Unwind Segues?)非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

您只能更改 NSDictionary 的可变子类中键的值,NSDictionary 本身是不可变的。

因此,由于您已更改为可变数组,因此您也可以对每个字典执行相同的操作:

filteredClientArray = [NSMutableArray arrayWithArray:sortedArray];
for(NSDictionary *d in [filteredClientArray copy])

    NSMutableDictionary * m = [d mutableCopy];
    [filteredClientArray replaceObjectAtIndex:[filteredClientArray indexOfObject:d] withObject:m];

【讨论】:

当然会保留可变副本,如果您不使用 arc,则必须处理它 感谢您的快速回复。那么我应该在更改keys 时将所有dictionaries 更改为mutable dictionaries 吗?还是应该在array 传递给最后一个ViewController 之前实现您的代码?我也在使用ARC 对不起,我在更改数据时在我的方法中添加了您的代码,并且使用我的NSPredicate predicateWithFormat:@"Client_Address_Line_1 == %@" 代码,我可以成功更改字典键。非常感谢! @rosshump,这个策略有一个微妙的错误,你不应该改变你正在迭代的集合......你应该制作一个数组的副本来迭代......在这种情况下应该没有任何问题,但它可能会引发异常......正在编辑。 可变复制。这为我节省了很多。谢谢老兄。

以上是关于更新/更改存储在 NSArray 中的 NSDictionary 键的值的主要内容,如果未能解决你的问题,请参考以下文章

通过取消引用更改 NSArray 中的值?

如何在一个文件中保存和检索多个 NSDictionaries

从存储在 NSDictionary 中的 JSON DATA 将应用程序名称存储在 NSArray 中

如何将 NSArray 值设置为 UILabel

如何快速发布存储在 NSArray var 中的字典数组?

如何在滚动视图中显示从 Web 获取的 NSArray 数据并在 Objective C 中扩展+更新它?