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

Objective c 更新/更改存储在NSArray中的NSDictionary键的值,objective-c,nsarray,nsdictionary,segue,nspredicate,Objective C,Nsarray,Nsdictionary,Segue,Nspredicate,我有一个NSArray包含NSDictionary的客户端数据。我正在使用NSPredicate过滤数组,并使用segues通过ViewControllers。我正处于更改字典中存储的键的某些值的阶段。这是如何实现的 我的prepareForSegue方法 if ([[segue identifier] isEqualToString:@"showClients"]) { // Detect selected row NSIndexPath *in

我有一个
NSArray
包含
NSDictionary
的客户端数据。我正在使用
NSPredicate
过滤
数组
,并使用
segues
通过
ViewControllers
。我正处于更改
字典中存储的键的某些值的阶段。这是如何实现的

我的
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;
        }
数组
现在只包含基于此
谓词的某些
字典
(即,当用户在
表视图
上选择一行时,假设
'Manchester'
,然后只有
字典
位置
曼彻斯特
被传递到下一个视图

下一个
TableView
上我的
prepareForSegue
方法与上一个类似,在本例中,我的
谓词
在所选行上过滤带有匹配姓氏的
词典
,并将其推送到下一个视图。现在,我剩下的
数组
构造如下:

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;
    }
)
我尝试了许多不同的方法来更新此
数组中的特定
字典键
,例如使用
谓词
,但似乎没有任何效果。例如:

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”而终止应用程序,原因:“[setValue:forUndefinedKey:]:此 类与密钥的键值编码不兼容 客户地址第1行。“

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

***由于未捕获的异常“NSUnknownKeyException”而终止应用程序,原因:“[setValue:forUndefinedKey:]: 此类不符合密钥的键值编码 客户地址第1行。“


似乎无论我做什么,我都无法更改或更新
数组中的任何
字典键
。经过数小时的研究,我开始怀疑这是否可能?我是否完全看错了方法?有没有更好的方法?在
更改后,我需要保存它们返回到
数组
并通过
视图控制器
将其传回(可能使用
展开序列
?)非常感谢您的帮助。

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

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

filteredClientArray = [NSMutableArray arrayWithArray:sortedArray];
for(NSDictionary *d in [filteredClientArray copy])
{
    NSMutableDictionary * m = [d mutableCopy];
    [filteredClientArray replaceObjectAtIndex:[filteredClientArray indexOfObject:d] withObject:m];
}

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

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

filteredClientArray = [NSMutableArray arrayWithArray:sortedArray];
for(NSDictionary *d in [filteredClientArray copy])
{
    NSMutableDictionary * m = [d mutableCopy];
    [filteredClientArray replaceObjectAtIndex:[filteredClientArray indexOfObject:d] withObject:m];
}

当然,可变副本将被保留,如果您不使用Arc,您将不得不处理这一问题。感谢您的快速回复。那么,我是否应该在更改
键时将所有
字典
更改为
可变字典
?还是应该在
数组
通过之前实现您的代码到最后一个
ViewController
?我也在使用
ARC
。很抱歉,我在更改数据时在我的方法中添加了您的代码,并使用我的
NSPredicate predicateWithFormat:@“客户端地址行1==%”
code,我可以成功地更改字典键。非常感谢!@rosshump,此策略中有一个微妙的错误,您不应该对正在迭代的集合进行变异…您应该复制数组以进行迭代…在这种情况下,不应该有任何问题,但可能会引发异常…编辑.mutableCopy。这为我节省了很多。谢谢,伙计。当然,可变副本将被保留,如果您不使用Arc,您将不得不处理它。谢谢您的快速回复。那么,我应该在更改
键时将所有
字典
更改为
可变字典
,还是应该实现您的代码d在
数组
传递到最后一个
视图控制器
之前?我也在使用
ARC
。很抱歉,我在更改数据时在我的方法中添加了您的代码,并使用了我的
NSPredicate predicateWithFormat:@“客户端地址行1==%”
code,我可以成功地更改字典键。非常感谢!@rosshump,此策略中有一个微妙的错误,您不应该对正在迭代的集合进行变异…您应该复制数组以进行迭代…在这种情况下,不应该有任何问题,但可能会引发异常…编辑.m这帮我省了不少钱谢谢伙计。