6

我对 StackOverflow 很陌生,所以如果我忘记了我的问题中的一些关键元素,请提前道歉。很长,请耐心等待!

遍历 JSON-webservice 结果:

对于 IOS5 iPad 应用程序,我从 Web 服务收集 JSON 信息,并通过:

NSData *data = [NSData dataWithContentsOfURL:url];
NSDictionary *json = 
[NSJSONSerialization JSONObjectWithData:data options:kNilOptions      
error:&error];

我将遍历返回NSDictionary并将返回的对象及其属性存储为自定义类。

自定义类包含几个属性,包括一个AmountInShoppingCart-value。

我使用这个自定义类来表示我们在商店中销售的商品,因此NSMutableArray由所有返回的对象组成并显示给用户。如果AmountInShoppingCart value > 0,那么对象将被放入ShoppingCart NSMutableArray(这是一个单例)。

在 ShoppingCart 中检查重复项:

为了确保ShoppingCart不包含任何重复的条目,我在ShoppingCartController(也从 SO 借来的)中有这样的函数:

- (void)checkForDuplicates
{
    NSMutableSet *seen = [NSMutableSet set];
    NSUInteger i = 0;
    NSLog(@"ShoppingCartArray count: %u",[ShoppingCartArray count]);
    //Iterate over the Array to check for duplicates, and to sync the list with the   
    cart.
    while (i < [ShoppingCartArray count]) {
        id obj = [ShoppingCartArray objectAtIndex:i];
        if ([seen containsObject:obj]) {
            if ([obj isKindOfClass:[MyCust class]]){
                MyCust *cust = [ShoppingCartArray objectAtIndex:i];
                MyCust *seenCust = [seen member:obj];
                seenCust.AmountInShoppingCart = cust.AmountInShoppingCart;
                [ShoppingCartArray removeObjectAtIndex:i];
            }} else {seen addObject:obj];
            i++;}}}

平等和散列

为此,我重写了isEqual:-class 的MyCust-function 以便它查看externalItemID-property,这是每个类对象绝对唯一的唯一属性。

我从 StackOverflow 中选择了这个函数:

- (BOOL)isEqual:(id)otherObject;
{
    if ([otherObject isKindOfClass:[MyCust class]]) {
        MyCust *otherCust= (MyCust *)otherObject;
        if (externalItemId != [otherCust externalItemId]) return NO;
        return YES;
    }
    return NO;
}

- (NSUInteger) hash;
{
    return [[self externalItemId] hash];
}

同步两个数组:

It can happen that people request the same result from the JSON-webservice, since it uses the MyCust's size, height and diameter to return a set of objects that adhere to those sizes.

So I use the following function to check and 'sync' the two NSMutableArrays with the new results:

In: RESULTLISTCONTROLLER.M

- (void) syncWithCart
{
    ShoppingCart *sc = [ShoppingCart sharedCart];
    [sc checkForDuplicates];
    NSMutableSet *listSet = [NSMutableSet setWithArray:resultList];
    NSUInteger i = 0;

    while (i < [sc.ShoppingCartArray count]) {
        id ShopObject = [sc.ShoppingCartArray objectAtIndex:i];
        if ([listSet containsObject:ShopObject])
        {
            MyCust *listCust = [listSet member:ShopObject];
            MyCust *shopCust = ShopObject;
            listCust.AmountInShoppingCart = shopCust.AmountInShoppingCart;
            [listSet removeObject:ShopObject];
        } else {i++;}}}

This all works pretty well until...

The 2nd webservice!

Now here comes the good part: There's a 2nd JSON-WebService the app uses to retrieve external supplier stock. It sometimes contains the same MyCust objects, but contains extra information that has to be parsed into the existing objects.

I basically get the first WebService's result into the getMyCustArray and the other in the getExternalCustArray. I then check if getMyCustArray contains an object in the getExternalCustArray and update the additional information on the objects and delete the similar object in getExternalCustArray. Any leftover objects only available from the supplier will be added using:

mergedCustArray = [NSMutableArray arrayWithArray:[getMyCustArray arrayByAddingObjectsFromArray:getExternalCustArray]];

Now the problem is, that when the user checks the same sizes twice, the App doesn't seem to consider the new results as the same.

When I do an NSLog of the ShoppingCartArray, the following shows: (original item names obfuscated)

First Search:

MyCust: SideShowBobsEarWarmers
 Hash: **2082010619**
 AmountInShoppingCart: 4
 **<MyCust: 0x81cee50>**",
    "
 MyCust: SolidSnakesCardBoardBox
 Hash: **4174540990**
 AmountInShoppingCart: 4
 **<MyCust: 0x8190d10>**" 

Second Search: the ResultList doesn't retain the MyCust's AmountInShoppingCart values, so I add them to the ShoppingCart again from the ResultList.

 MyCust: SideShowBobsEarWarmers
 Hash: **2082010619**
 AmountInShoppingCart: 4
 **<MyCust: 0x81cee50>**",

 MyCust: SolidSnakesCardBoardBox
 Hash: **4174540990**
 AmountInShoppingCart: 4
 **<MyCust: 0x8190d10>**" 
    "
// Different Pointers, although they should be considered Equal.

 MyCust: SideShowBobsEarWarmers
 Hash: **2082010619**
 AantalInWinkelWagen: 3
 **<MyCust: 0x74bc570>**",      
    "
 MyCust: SolidSnakesCardBoardBox
 Hash: **4174540990**
 AantalInWinkelWagen: 2
 **<MyCust: 0x74bc7b0>**"

So somehow the compiler allocates those objects in a different memory address/pointer, and then breaks the isEqual: function, as far as I can tell.

My guts tell me there's something to do with NSCopy(able), but I'm not quite sure how I'd implement that. If anyone got some good tips for a Shopping Cart system, that's always welcome too. I've got half a mind converting all this to Core Data but would like to have the core functionality in place before doing that.

4

1 回答 1

3

In isEqual: method, the line "if (externalItemId != [otherCust externalItemId]) return NO;" is wrong. I think it should be if (![externalItemId:isEqual:[otherCust externalItemId]]) return NO;

于 2012-11-14T19:30:30.030 回答