JoshDG
JoshDG

Reputation: 3931

iOS: Object equality when enumerating

Say I have a NSArray, and each item is an NSDictionary with three keys keyA, keyB, and keyC - each referring to objects of unknown type (id).

If I wanted to write a method that found the given element with those three keys i.e.

-(NSDictionary *) itemThatContainsKeys:(id)objectA and:(id)objectB and:(id)objectC

would I run into trouble by simply enumerating through and testing object equality via if([i objectForKey:(keyA) isEqualTo:objectA]) etc? I would be passing in the actual objects that were set in the dictionary initialization - ie not strings with the same value but different locations.

Is this bad practise? Is there a better way to do this without creating a database?

Upvotes: 2

Views: 105

Answers (2)

Jasper Blues
Jasper Blues

Reputation: 28786

You can override isEqual to stipulate the notion of equality for your type. The same rules apply as in other languages:

  • If you provide an implementation of equals you should provide an implementation of 'hash'
  • Objects that are 'equal' should have the same 'hash'
  • Equals should be transitive -> if A equals B, and B equals C, then C must equal A.
  • Equals should be bi-directional -> if A equals B, then B must equal A.

This will ensure predictable behavior in classes like NSSet, that use hash for performance, falling back to equals on when there's a collision.

As Jason Whitehorn notes, Objective-C also has the convention of providing another isEqualToMyType method for convenience.

AppCode, EqualsBuilder, Boiler-plate code

It would be nice if there was something like Apache's 'EqualsBuilder' class, but in the meantime AppCode does a fine job of implementing these methods for you.

Upvotes: 1

Jason Whitehorn
Jason Whitehorn

Reputation: 13685

The isEqual: method compares object identity unless overwritten by a subclass. Depending on what class the target is, this May or may not be what you want. What I prefer is to use a more class specific comparison like isEqualToNumber: simply because of it's explicitness. But, isEqual should work depending on the target.

Other than that, and not knowing more specifics of what you're doing, it's hard to say if there is a better way to accomplish what you're after. But, here are my thoughts;

An array of a dictionary almost sounds like you might need a custom class to represent some construct in your app. Perhaps the dictionary could be replaced with a custom object on which you implement an isEqualToAnotherThing: method. This should simplify your logic.

Upvotes: 0

Related Questions