我对 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.