从 NSDictionary 中删除密钥

Posted

技术标签:

【中文标题】从 NSDictionary 中删除密钥【英文标题】:Deleting key from NSDictionary 【发布时间】:2011-10-24 22:12:35 【问题描述】:

在我的应用程序中,我将一组数据集存储在 NSUserDefaults 中。当需要访问它时,我创建了一个数组(NSUserDefaults 中的每个键都包含数据数组)并使用该数据。它工作得很好。耶!不幸的是,当我在 UITableView 中显示数据时,删除一组数据(其中 == UITableView 中的一行)无法正常工作。这就是我要做的事情:

if(buttonIndex == actionSheet.destructiveButtonIndex)

    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];

    int iii = [defaults integerForKey:@"currentMap"];

    NSMutableDictionary* dicOne = (NSMutableDictionary*)[[NSUserDefaults standardUserDefaults] dictionaryRepresentation];

    for(int lll = iii; lll < [[defaults objectForKey:@"counterKey"] intValue]; lll++)
    
        if(lll != [[defaults objectForKey:@"counterKey"] intValue] - 1)
            [dicOne setObject:[dicOne objectForKey:[NSString stringWithFormat:@"%i", (iii + 1)]] forKey:[NSString stringWithFormat:@"%i", iii]];

        else
            [dicOne removeObjectForKey:[NSString stringWithFormat:@"%i", iii]];
    

    [defaults setPersistentDomain:dicOne forName:[[NSBundle mainBundle] bundleIdentifier]];

    [defaults synchronize];

    int counter = [defaults integerForKey:@"counterKey"];

    counter--;

    [defaults setInteger:counter forKey:@"counterKey"];

    [defaults synchronize];

    [self performSelector:@selector(done:) withObject:nil afterDelay:.3];

此代码背后的想法是在要删除的选定行的索引处开始一个 for 循环(变量“iii”)。此方法在字典中移动,将每个索引向下移动一个级别。

假设字典包含五组数据(五个键),分别标记为 0、1、2、3 和 4。当 2 被标记为删除时,此代码在字典中移动,将键 3 中包含的数据分配给key 2,key 4 中的数据到 key 3,然后删除 key 3 中剩余的副本。然后 counterKey 递减(因为这是我用来跟踪存在多少键的数字,所以我可以告诉 UITableView 它需要创建多少个单元格)。或者至少这是我认为它应该做的。

但它并没有做我认为它应该做的事情;当一个单元格被标记为删除时,真正发生的是该键的数据显示为 NULL,并且键不会像我认为的那样“滑动”。

done: 方法关闭信息视图(包含删除按钮和有关所选行的信息)并返回到包含 UITableView 的视图。

这个概念有意义吗?如果是,为什么它不起作用?感谢您的宝贵时间。

***编辑:

谢谢你,jrturton,使用 NSArray 有效,但有时删除它(或尝试)会因此错误而崩溃:

* 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object” * 首先抛出调用栈: (0x14c7052 0x1658d0a 0x146fa78 0x146f9e9 0x14c109f 0xd381 0x8cba1f 0x14c8ec9 0x5105c2 0x51055a 0x5b5b76 0x5b603f 0x5b52fe 0x535a30 0x535c56 0x51c384 0x50faa9 0x24adfa9 0x149b1c5 0x1400022 0x13fe90a 0x13fddb4 0x13fdccb 0x24ac879 0x24ac93e 0x50da9b 0x1ef9 0x1e75) P>

这很奇怪,因为该类中没有使用单个 NSArray;它们都是可变的。

这是崩溃的路线(我有理由确定):

NSMutableArray* outerArray = (NSMutableArray*)[defaults objectForKey:@"mapSaveDataKey"];
[outerArray removeObjectAtIndex:iii];

修复:

替换:

[defaults objectForKey:@"mapSaveDataKey"]; 

与:

[defaults mutableArrayValueForKey:@"mapSaveDataKey"];

【问题讨论】:

您可以通过进行有意义的编辑或在您的问题中添加赏金来“碰撞”帖子。如果您没有回复,您可能需要让问题更清楚。您不应该添加这样的答案 - 它将被删除。 好的,谢谢你的澄清。 你是从 NSUserDefaults 中提取你的数组吗?信不信由你,你从 NSUserDefaults 得到的任何东西都是不可变的,即使你最初给它一个可变的值。从 Apple 的文档中,“从 NSUserDefaults 返回的值是不可变的,即使您将可变对象设置为值。”尝试做 NSMutableArray *outerArray = [NSMutableArray arrayWithArray:[defaults objectForKey:@"mapSaveDataKey"]]; 【参考方案1】:

您正在做的事情似乎不必要地复杂。为什么不在一个键(例如@"data")下将单个数组存储在用户默认值中,然后删除或添加项目到该数组?这样您就不必维护单独的计数或类似的东西。例如,您可以使用objectAtIndex: 来获取第 4 项,当您删除第 2 项时,它上面的项目无论如何都会下移一个档次。

更新 - 正如 Matthew Gillingham 在 cmets 中指出的那样,我的意思是可变数组。正如您所发现的,您无法更改NSArray 中元素的数量或位置。

还要注意arrayForKey: 将返回一个NSArray,即使您首先存储了一个可变数组,所以当从默认值获取值时,您必须执行以下操作:

NSMutableArray *myData = [NSMutableArray arrayWithArray:[defaults arrayForKey:@"data"]];

defaults 是您的用户默认对象。

【讨论】:

看似简单,工作精美。只有一个问题。当数组中只有一个对象时,尝试删除它会崩溃:*** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object”***第一掷调用堆栈:(0x14c7052 0x1658d0a 0x146fa78 0x146f9e9 0x14c109f 0xd381 0x8cba1f 0x14c8ec9 0x5105c2 0x51055a 0x5b5b76 0x5b603f 0x5b52fe 0x535a30 0x535c56 0x51c384 0x50faa9 0x24adfa9 0x149b1c5 0x1400022 0x13fe90a 0x13fddb4 0x13fdccb 0x24ac879 0x24ac93e 0x50da9b 0x1ef9 0x1e75)跨度> 也许你应该使用 NSMutableArray 而不是 NSArray? @matthewgillingham:感谢您的澄清。我已经更新了我的答案。 您的回答让我朝着正确的方向前进;这是我发现的,它有效: NSMutableArray* array = [defaults mutableArrayValueForKey:@"mapSaveDataKey"];

以上是关于从 NSDictionary 中删除密钥的主要内容,如果未能解决你的问题,请参考以下文章

我的 NSDictionary 的密钥是啥

从 JSON 响应设置 NSDictionary 中的值

如何在 iOS 中获取音频文件的持续时间?

检查 NSDictionary 中的键 - 不使用布尔 NSNumber 作为值 @iOS8

如何从 NSDictionary 中删除对象

如何从 NSDictionary 中删除空值