2010-10-28 44 views
1

编辑:更好的例子...合并一个NSArray成的NSSet和避免对iphone在Objective-C复制

所以我有“现有”对象的的NSMutableSet,我想下载JSON数据,解析它,并将这些新对象与我现有的对象合并,使用新下载的对象更新任何重复对象。下面是现有的一组对象的样子:


NSArray *savedObjects = [NSArray arrayWithObjects: 
    [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"id", @"hello there", @"body", @"200", @"score", nil], 
    [NSDictionary dictionaryWithObjectsAndKeys:@"2", @"id", @"hey now", @"body", @"10", @"score", nil], 
    [NSDictionary dictionaryWithObjectsAndKeys:@"3", @"id", @"welcome!", @"body", @"123", @"score", nil], 
    nil 
]; 
self.objects = [NSMutableSet setWithArray:savedObjects]; 

// after downloading and parsing JSON... I have an example array of objects like this: 

NSArray *newObjects = [NSArray arrayWithObjects: 
    [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"id", @"hello there", @"body", @"9999", @"score", nil], 
    [NSDictionary dictionaryWithObjectsAndKeys:@"4", @"id", @"what's new", @"body", @"22", @"score", nil], 
    nil 
]; 

因此,例如,合并这个新的对象之后,ID为1的对象将现在的9999分和ID为4的新对象将被添加到集合。

我真的想避免循环每个新对象的NSMutableSet只是为了检查@“id”属性存在......我想我可以使用addObjectsFromArray来合并这些新的对象,但它看起来像是因为属性不同(例如:分数:9999)它不会将新对象看作集合中的现有对象。

我使用的数字作为字符串来简化这个例子。我也想避免使用仅适用于iOS SDK 4.0的功能,因为该应用将与3.0兼容。

谢谢!我很感激!

+0

为什么要构建一个NSArray并立即转换是一个NSSet中?您应该直接为保存的对象使用'[NSSet setWithObjects:...]'。 – 2010-10-28 22:43:15

+0

哦,好吧,我想我不得不因为他们以前也是JSON。 setWithObjects在传递数组时是否工作?谢谢。 – taber 2010-10-28 22:53:39

+0

'+ [NSSet中setWithObjects:]'工作就像'+ [NSArray的arrayWithObjects:]'不同之处在于它返回一个集而不是阵列。 – 2010-10-29 01:01:35

回答

0

最好的办法是使用@“id”参数将第一组转换成字典。这里有一些代码应该做你想做的事情,它甚至可以处理没有@“id”参数的字典(在这一点上它们不会被合并,只包括在结果中):

// here is the NSSet you already have 
self.objects = [NSSet setWithObjects: 
    [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"id", @"hello there", @"body", @"200", @"score", nil], 
    [NSDictionary dictionaryWithObjectsAndKeys:@"2", @"id", @"hey now", @"body", @"10", @"score", nil], 
    [NSDictionary dictionaryWithObjectsAndKeys:@"3", @"id", @"welcome!", @"body", @"123", @"score", nil], 
    nil]; 

// after downloading and parsing JSON... I have an example array of objects like this: 

NSArray *newObjects = [NSArray arrayWithObjects: 
    [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"id", @"hello there", @"body", @"9999", @"score", nil], 
    [NSDictionary dictionaryWithObjectsAndKeys:@"4", @"id", @"what's new", @"body", @"22", @"score", nil], 
    nil]; 

// Convert self.objects into a dictionary for merging purposes 
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:[self.objects count]]; 
NSMutableSet *remainder = [NSMutableSet set]; // for objects with no @"id" 
for (NSDictionary *obj in self.objects) { 
    NSString *objId = [obj objectForKey:@"id"]; 
    if (objId) { 
     [dict setObject:obj forKey:objId]; 
    } else { 
     [remainder addObject:obj]; 
    } 
} 

// merge the new objects in 
for (NSDictionary *obj in newObjects) { 
    NSString *objId = [obj objectForKey:@"id"]; 
    if (objId) { 
     // merge the new dict with the old 
     // if you don't want to merge the dict and just replace, 
     // simply comment out the next few lines 
     NSDictionary *oldObj = [dict objectForKey:objId]; 
     if (oldObj) { 
      NSMutableDictionary *newObj = [NSMutableDictionary dictionaryWithDictionary:oldObj]; 
      [newObj addEntriesFromDictionary:obj]; 
      obj = newObj; 
     } 
     // stop commenting here if you don't want the merging 
     [dict setObject:newObj forKey:objId]; 
    } else { 
     [remainder addObject:obj]; 
    } 
} 

// add the merged dicts back to the set 
[remainder addObjectsFromArray:[dict allValues]]; 
self.objects = remainder; 
4

不能完全确定从你的问题(因为本来应该使用它的一个iphone的问题,Objective C的符号),但它听起来像一个NSDictionary可能是你最好的朋友。

+0

确实。这是一个尝试使用一个字典集,这就是为什么它看起来很尴尬。 – Chuck 2010-10-28 19:08:10

+0

比较遗憾的是这只是更快地打字了,我只是把它抓住晚饭前。我已经更新了代码,它现在应该更有意义。 :) 谢谢! – taber 2010-10-28 22:15:42

0
NSArray *array = ... // contains the new dictionary objects. 
NSMutableSet *set = ... // contains the existing set of dictionary objects. 

for (id arrayItem in array) 
{ 
    id setItem = [[set filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"id.intValue = %d", [[arrayItem valueForKey:@"id"] intValue]]] anyObject]; 
    if (setItem != nil) 
    { 
     [set removeObject:setItem]; 
     [set addObject:arrayItem]; 
    } 
} 
+0

嗨,这将与iOS 3.0的工作?我忘了提及我想避开iOS 4.0 API。谢谢! – taber 2010-10-28 22:16:31

+0

对不起,但predicateWithBlock需要4.0。 – tidwall 2010-10-28 22:41:59

+0

哦,我是这么认为的,我还是谢谢你,感激 – taber 2010-10-28 22:55:34