【问题标题】:a faster way to mutate an Array of NSMutableDictionaries一种改变 NSMutableDictionaries 数组的更快方法
【发布时间】:2013-05-10 09:15:15
【问题描述】:

基于您cannot 在枚举可变集合时编辑可变集合这一事实,这是我能想出的编辑 NSMutableDictionaries 数组的最佳解决方案:

__block NSMutableDictionary *tempDict = [NSMutableDictionary dictionaryWithCapacity:1];
__block NSUInteger idx;
[_myArray enumerateObjectsUsingBlock:^(NSMutableDictionary* obj, 
                                                        NSUInteger indx, BOOL *stop) {
    if (// some condition is met) {
        tempDict = [obj mutableCopy];
        idx = indx;
    }
}];

[tempDict setObject:[NSNumber numberWithInt:thisQueryResults] forKey:@"resultsNum"];
[_myArray replaceObjectAtIndex:idx withObject:rowSelected];

这似乎太复杂了(即使对于像 obj-c 这样的语言).. 由于它涉及两种数据类型(NSMutableArray 和 NSMutableDictionary),我似乎无法将它们清晰地归入一个类别.. 建议?

更新:一条评论问我为什么要创建一个可变副本(而不是只是一个副本......因为它正在复制一个可变对象)..

假设我只是使用了副本.. 如果我在 tempDict 上打断,这就是我得到的:

// tempDict = [obj copy]
po tempDict
$0 = 0x0b28cc10 <__NSArrayI 0xb28cc10>(
1
)

// tempDict = [obj mutableCopy]
po tempDict
$0 = 0x0b28cc10 <__NSArrayM 0xb28cc10>( //notice the M in __NSArrayM as opposed to I above
1
)

在复制的情况下..如果我在后面加上这样的一行: [tempDict setObject:[NSNumber numberWithInt:thisQueryResults] forKey:@"resultsNum"];

我得到这个错误:

[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance 0xb245100

this 代码也出现上述错误:

for (NSUInteger idx = 0; idx < [_myMutableArray count]; idx++) {
    NSMutableDictionary* myMutableDict = _myMutableArray[idx];
    [myMutableDict setObject:obj forKey:key];        
}

更新 2: 问题的根源是实例化非可变数组和字典。我是全新 obj-c literals 的新手,所以我不知道要创建 NSMutableArray 和 NSDictionary,你必须分别这样做:

[@[..] mutableCopy]
[@{..} mutableCopy]

【问题讨论】:

  • +1 表示它太复杂了

标签: ios objective-c nsmutablearray enumeration nsmutabledictionary


【解决方案1】:

所以在你的情况下,我不太明白你为什么叫 tempDict = [obj mutableCopy];当从你写的条件下,字典已经是可写的了。

您可以使用多种技巧。喜欢使用

for (NSUInteger idx = 0; idx < _myArray.count: idx++_ {
   NSMutableDictionary *obj = _myArray[idx];

  // modify
}

对于 NSDictionaries,您可以获得 allKeys 并遍历该副本。这比使用快速枚举要慢一些,但仍然比使用装箱整数等变通方法更快:)

【讨论】:

  • 恐怕它不起作用..这是我尝试过的:` for (NSUInteger idx = 0; idx -[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance 0xb245100 出于某种原因,它会将 NSMutableDictioanry 转换为 __NSDictionaryI.. 这与我在使用丑陋的解决方案之前遇到的错误相同
  • 然后你需要检查你的数组 - NSArray 只保留而不复制对象,所以在你的代码中的某个地方你添加了不可变的数据结构。但是你总是可以添加一个 mutableCopy - 当 NSDictionary 已经是可变的时,这只是简单地保留对象。
【解决方案2】:

在您的情况下,您根本不会只修改数组中的字典。关于如何修改数组中的对象没有任何限制。下面是一段等价的代码:

for (NSMutableDictionary *dict in _myArray) {
    if (someCondition)
         [dict setObject:[NSNumber numberWithInt:thisQueryResults] forKey:@"resultsNum"]
}

如果您绝对需要替换数组中的对象,您将遇到问题。在这种情况下,如果数组不是很大,我会建议与@Markus 相同。遍历副本并修改原始文件。

【讨论】:

  • 您收到此错误的原因是,尽管您认为数组中有可变字典,但实际上并非如此。查看代码中最初创建此数组的位置并向其中添加字典并确保它们是可变字典。提示:@{} 将创建一个 NSDictionary 而不是 NSMutableDictionary。不过你可以做[@{} mutableCopy]
【解决方案3】:

也许你可以使用 KVC 做:

NSArray<NSMutableDictionary *> *result = [[_myArray filteredArrayUsingPredicate:[NSPredicate withFormat:@"{YOUR CONDITION}"]] valueForKey:@"mutableCopy"];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-13
    • 2011-02-14
    • 1970-01-01
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    相关资源
    最近更新 更多