Note that there are some explanatory texts on larger screens.

plurals
  1. POIOS 5: How to return YES on contains: with 2 'identical' objects, but with different pointers
    primarykey
    data
    text
    <p>I'm quite new to StackOverflow, so apologies in advance if I forgot some critical element in my question. It's a long one, so bear with me!</p> <p><strong>Iterating over JSON-webservice result:</strong></p> <p>For an IOS5 iPad app, I collect JSON information from a webservice and via: </p> <pre><code>NSData *data = [NSData dataWithContentsOfURL:url]; NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&amp;error]; </code></pre> <p>I'll iterate over the returned <code>NSDictionary</code> and store the returned objects and their properties as a custom class.</p> <p>The custom class contains several properties, including an <code>AmountInShoppingCart</code>-value.</p> <p>I use this custom class to represent items that we sell in our store, so an <code>NSMutableArray</code> is made of all the returned objects and shown to the user. If the <code>AmountInShoppingCart value &gt; 0</code>, then the object will be put in the <code>ShoppingCart</code> <code>NSMutableArray</code> (which is a singleton).</p> <p><strong>Checking for duplicates in ShoppingCart:</strong></p> <p>To make sure the <code>ShoppingCart</code> doesn't contain any duplicate entries, I've got a function like this in the <code>ShoppingCartController</code> (also borrowed from SO):</p> <pre><code>- (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 &lt; [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++;}}} </code></pre> <p><strong>Equality &amp; Hashing</strong></p> <p>To accomplish this, I've overridden the <code>isEqual:</code>-function of the <code>MyCust</code>-class so that it'll look at the <code>externalItemID</code>-property, which is the only property that is definitely unique for each class object. </p> <p>I picked this function up from StackOverflow:</p> <pre><code>- (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]; } </code></pre> <p><strong>Sync the two arrays:</strong></p> <p>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.</p> <p>So I use the following function to check and 'sync' the two NSMutableArrays with the new results:</p> <pre><code>In: RESULTLISTCONTROLLER.M - (void) syncWithCart { ShoppingCart *sc = [ShoppingCart sharedCart]; [sc checkForDuplicates]; NSMutableSet *listSet = [NSMutableSet setWithArray:resultList]; NSUInteger i = 0; while (i &lt; [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++;}}} </code></pre> <p>This all works pretty well until...</p> <p><strong>The 2nd webservice!</strong></p> <p>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 <code>MyCust</code> objects, but contains extra information that has to be parsed into the existing objects.</p> <p>I basically get the first WebService's result into the <code>getMyCustArray</code> and the other in the <code>getExternalCustArray</code>. I then check if <code>getMyCustArray</code> contains an object in the <code>getExternalCustArray</code> and update the additional information on the objects and delete the similar object in <code>getExternalCustArray</code>. Any leftover objects only available from the supplier will be added using:</p> <pre><code>mergedCustArray = [NSMutableArray arrayWithArray:[getMyCustArray arrayByAddingObjectsFromArray:getExternalCustArray]]; </code></pre> <p>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.</p> <p>When I do an NSLog of the ShoppingCartArray, the following shows: (original item names obfuscated)</p> <p><strong>First Search:</strong></p> <pre><code>MyCust: SideShowBobsEarWarmers Hash: **2082010619** AmountInShoppingCart: 4 **&lt;MyCust: 0x81cee50&gt;**", " MyCust: SolidSnakesCardBoardBox Hash: **4174540990** AmountInShoppingCart: 4 **&lt;MyCust: 0x8190d10&gt;**" </code></pre> <p><strong>Second Search:</strong> the ResultList doesn't retain the MyCust's AmountInShoppingCart values, so I add them to the ShoppingCart again from the ResultList.</p> <pre><code> MyCust: SideShowBobsEarWarmers Hash: **2082010619** AmountInShoppingCart: 4 **&lt;MyCust: 0x81cee50&gt;**", MyCust: SolidSnakesCardBoardBox Hash: **4174540990** AmountInShoppingCart: 4 **&lt;MyCust: 0x8190d10&gt;**" " // Different Pointers, although they should be considered Equal. MyCust: SideShowBobsEarWarmers Hash: **2082010619** AantalInWinkelWagen: 3 **&lt;MyCust: 0x74bc570&gt;**", " MyCust: SolidSnakesCardBoardBox Hash: **4174540990** AantalInWinkelWagen: 2 **&lt;MyCust: 0x74bc7b0&gt;**" </code></pre> <p>So somehow the compiler allocates those objects in a different memory address/pointer, and then breaks the <code>isEqual:</code> function, as far as I can tell.</p> <p>My guts tell me there's something to do with <code>NSCopy(able)</code>, 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.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload