2010-10-28 20 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