I want to know how NSSet make sure that it has only unique objects? When we try to add duplicate value, then on which criteria it decides that it has already this value? I want to know the underlying uniqueness criteria.
NSSet uses your object's implementation of isEqual: method to decide object equality. It also uses hash to make the lookup much faster.
-(BOOL)isEqual:(id)other;
-(NSUInteger)hash;
When two objects are equal, their hash methods must return the same value (objects with the same hash, however, may not necessarily be equal to each other).
When your hash and isEqual: are implemented properly, NSSet can decide the equality by checking only a handful of objects whose hash "collides" with the hash of the object you are adding to the set.
take a look at Object Comparison in the official apple documentation. As you can see there most of the containers use hash to compare objects.
I want to know how NSSet make sure that it has only unique objects
Whenever you try to add object it will check for hash value of all other existing objects inside of it. Based on that it will keep it as unique
If two objects are equal, they must have the same hash value
When we try to add duplicate value, then on which criteria it decides that it has already this value?
if the new object hash value matches the existing then it will be considered as dublicate
Refer this Apple's documentation
First of all the set checks hash values of objects. If hashes are not equal it means that objects are guaranteed to be different. If hashes are equal it however doesn't mean that objects are neccessarily equal, so the set has to make sure and check their isEqual: methods
Related
how to check if an array is sorted?
I am sorting using sort descriptors. Is there any API to check if an array is already in sorted order in Swift/Objective-C.
Thanks
i think there is no frame work, simply iterate truth the array, and check if the current element greater or equal (or less or equal, or which kind of sorting you look for) is. This is the easiest way. Look please at this Question Solution
As far as I know, there isn't a built in way to check if an array is already sort descriptors. The best way to check is to iterate through the array and check if each element should come before the element precedes it (using whatever definition of "should come before" you want for your sort). If you're sorting custom objects, you can write some sort of compareTo method that compares two objects of your class, which will make it convenient to check using the method I described.
I am trying to do array comparison on 2 mutable arrays. In one of the array, i am storing my model objects and in the other array I am storing a copy of the model objects using [myObject copy]. My model object is a subclass of NSObject so I have added the copyWithZone: method as well. However when I do array compare using isEqualToArray on these two arrays it always returns false. Will the compare not work on copied objects? Or am I going wrong somewhere else?
P.S: As an overview, what I'm trying to do is to check whether something is changed in my model before calling an update service. I want to call the service Only if any of the model objects have changed.
Will the compare not work on copied objects?
You can very easily find out the answer to this question by just copying a single object and checking for equality agains the original.
SPOILER
The results you are going to see will depend on if you have implemented custom hash and isEqual: methods in your class. Without those it will default to the superclasses implementation (NSObject) which considers equality to be the same pointer. Since a copy is a new pointer to the same object, NSObject won't consider them equal.
I would recommend that you read about object equality in this NSHipster article (great to start with) and/or in this article by Mike Ash (if you are feeling curious)
Method isEqualToArray acts as follows. It takes one by one the next objects from two arrays and compare them using isEqual. The latter compares hash (NSInteger property) of NSObjects (or its subclasses).
In general it is the address of the object. hash can be redefined while subclassing but it may cause big problems.
For copied objects you will have different hashes. And thus isEqualToArray is always FALSE.
But if you use simple data classes like NSNumber, NSString as elements to compare, you will get TRUE under copying them.
I have 2 Core Data objects of the same type. I got them via different ways.
At the same time these objects have an NSString field (identifier).
So what is better?
1)compare objects via isEqual:
2)compare objects via == (is it possible in general?)
3)compare objects' fields via isEqualToString:?
Basically, never use == on objects. Always use isEqual:.
If you're using a predicate then you can use LIKE on the identifier.
If you are trying to determine whether or not two objects are the semantically equal and you can describe what equality looks like for that type, then use isEqual. For example, if you have a Person class, you might define equality based on SSN (in the US) or something equally unique.
If you are trying to determine that two objects have something specific in common, but it doesn't necessarily imply that they are equal (for example, using the same Person example, if you want find out if two instances have the same last name), compare the attributes using isEqualToString:. It would not make sense to put this comparison into isEqual for the type.
If you are trying to find out if you have two NSManagedObject instances from your persistent store that are actually the same object fetched via different NSManagedObjectContexts, use the objectID for comparison.
Assuming I have a hash value of some NSObject during runtime.
Is there a way to find a pointer to that object using just hash value?
I don't want to store pointers to objects and their hashes as keys. I imagine that iOS already doas that.
There is no way, not even an unreliable way, to do this.
Many objects have hashes in ways that makes it impossible to reference it. You will have duplicates because of this. One example, as #Martin said, is NSArrays. NSArrays' hashes are just the number of elements in the array.
I'm facing a case in my application where I need a bidirectional dictionary data structure, that means a kind of NSDictionary where your can retrieve a key with a value and a value with a key (all values and keys are unique).
Is there such a kind of data structure in C / ObjectiveC ?
You can do it with a NSDictionary:
allKeysForObject: Returns a new array containing the keys
corresponding to all occurrences of a given object in the dictionary.
(NSArray *)allKeysForObject:(id)anObject Parameters anObject The value to look for in the dictionary. Return Value A new array
containing the keys corresponding to all occurrences of anObject in
the dictionary. If no object matching anObject is found, returns an
empty array.
Discussion Each object in the dictionary is sent an isEqual: message
to determine if it’s equal to anObject.
And:
objectForKey: Returns the value associated with a given key.
(id)objectForKey:(id)aKey Parameters aKey The key for which to return the corresponding value. Return Value The value associated with
aKey, or nil if no value is associated with aKey.
Literally, the answer is No.
As a workaround you may create a helper class which manages two dictionaries.
Another approach is to create a thin wrapper around C++ container which implement this: boost's Bimap.
When using ARC and Objective-C objects as values or keys in C++ containers, they will handle NSObjects quite nicely. That is, they take care of memory management as you would expect - and you even get "exception safety" for free. Additionally, C++ standard containers are also a tad faster, use less memory, and provide more options to optimize (e.g. custom allocators).