从 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 中删除密钥的主要内容,如果未能解决你的问题,请参考以下文章