What is the diference between these two methods belonging to the NSSet class:
-(BOOL)containsObject:(id)anObject
-(id)member:(id)object
The answer lies in the return values. containsObject returns a YES or a NO depending on if the object you send belongs to that particular set.
member returns id, which means that it returns the actual object if that object is part of the set.
As an example, you have an NSSet, aSet, with anObject. anObject belongs to the set.
[aSet containsObject:anObject]; //returns YES
[aSet member:anObject]; //If the set contains an object equal to object (as determined by isEqual:) then that object (typically this will be object), otherwise nil.
If anObject does not exist in aSet:
[aSet containsObject:anObject]; //return NO
[aSet member:anObject]; //return nil
Related
The documentation for Set's insert method states:
Return Value
(true, newMember) if newMember was not contained in the set. If an element equal to newMember was already contained in the set, the method returns (false, oldMember), where oldMember is the element that was equal to newMember.
In some cases, oldMember may be distinguishable from newMember by identity comparison or some other means.
What are the cases when oldMember might be distinguishable from newMember they are talking about? Any example?
Reason for the question: I have a Set that contains objects that are not necessarily Hashable. I had the idea to use Unmanaged.passUnretained(object).toOpaque().hashValue to get a hash-value for just any object (basically from its address) in a wrapper struct, however the above bit in the documentation makes me wary.
If you have some way to tell two instances apart even when they compare equal by their implementation of Equatable's == operator, then you can use this to compare the element to insert with the memberAfterInsert returned by insert(_:).
A prime example of this, as the documentation says, is the identity comparison (===). Two object instances that compare equal may not necessarily be the exact same instance (i.e have the same address).
For example:
class Foo : Hashable {
static func ==(lhs: Foo, rhs: Foo) -> Bool {
return lhs.foo == rhs.foo
}
var hashValue: Int {
return foo
}
let foo: Int
init(_ foo: Int) {
self.foo = foo
}
}
var set : Set = [Foo(10)]
let toInsert = Foo(10)
let result = set.insert(toInsert) // the element toInsert will compare equal to the element
// already in the set, thus the element already in the
// already in the set will be returned.
print(result) // (false, Foo) – false, as element was already in set
print(result.memberAfterInsert == toInsert) // true – obviously they were equal.
print(result.memberAfterInsert === toInsert) // false – but they weren't the same instance.
In your case of using a hash value based on the identity, as long as your Equatable implementation also relies on the identity, you won't break the contract of Hashable (instances that compare equal with == must have the same hashValue) – although obviously you won't be able to use the identity to differentiate the memberAfterInsert with the element you are trying to insert.
However it's worth noting that having a Set where the Element's equality implementation is solely based on identity may cause surprising results for objects that look like they should be equivalent. For example, it would be perfectly fine to have a set of [Foo(5), Foo(5), Foo(5), Foo(5)], given that the objects are different instances.
I have a method that creates an object an returns it as usual.
func myFunction() -> MyObject?{
var object = MyObject()
debugging it I can see that at the end of this function this object has a valid memory address.
return object
}
However when I receive it instead of displaying nil or the object address I can see the word "some". If I compare this object with nil it is not evaluated as a non nil object.
result = something.myFunction()
if result != nil {
println("never reaches here")
}
what is going on?
You've declared that method to return an optional MyObject. In Swift, optionals are implemented as an enum that has two possible values: .None, which is usually seen in its literal form, nil, and .Some, which holds the value of the optional as an associated value. You're seeing Some in the debugger because your method successfully returns a value wrapped in an optional.
You can read more about Optionals in the Swift language guide.
I am checking if an object I am getting back from the NSURLConnectionDataDelegate is the same object that I originally created. What I have been doing is:
// TESTING TO SEE IF THE RETURNED OBJECT IS THE SAME ONE I CREATED
if(connection == [self connectionPartial]) {
But was just curious is this is the same as doing:
if([connection isEqual:[self connectionPartial]]) {
It's not the same.
if(connection == [self connectionPartial]) {
This compares the address of the objects, eg. if the pointers point to the same instance.
if([connection isEqual:[self connectionPartial]]) {
This compares the contents of the objects. For instance for two separate NSString instances, this will return YES as long as the string content is the same:
NSString *s1 = #"Something";
NSString *s2 = #"Something";
BOOL sameInstances = (s1 == s2); // will be false, since they are separate objects.
BOOL sameContent = [s1 isEqual:s2]; // will be true, because they both are "Something"
The first snippet compares the values of the pointers themselves, just as if they were any primitive type like an int. If the addresses are the same, the expression will evaluate true.
The second sends the message isEqual: to one of the connection instances. Any class can override isEqual: to define "equality" with another instance. It's entirely possible for a class's implementation of isEqual: to be:
- (BOOL)isEqual: (id)obj
{
return arc4random_uniform(2) ? YES: NO;
}
So, no, for almost all classes they are not equivalent. (NSObject, which has the "default" implementation of isEqual:, uses the objects' hashes, which, again by default, are their addresses.)
It sounds like using the equality operator, ==, is correct in your case.
I have an array of current animal objects that can be viewed by day - for example, monday will return all animals that are available on a monday, etc.
I also have an array of saved animal objects.
How do I ensure that the saved animals don't show up in the current animals list?
Something like, if the currentAnimal.name isEqual to savedAnimal.name?
I need the objects in both arrays so it is important to compare the .name properties, I think?
Override isEqual and hash to do a comparison on the name if that is what you consider to make the objects 'equal'.
- (BOOL)isEqual:(id)other {
if (other == self)
return YES;
if (!other || ![other isKindOfClass:[self class]])
return NO;
return [((MyObject *)other).name isEqualToString:name];
}
and
- (NSUInteger)hash {
return [name hash];
}
You should use isEqual method if you want objects strictly equals or method isKindOfClass.
Look at NSObject reference
Do
for (id object in array) {
// do something with object
}
guarantee to return the objects in the order they are put in the array?
It's just shorthand for an enumerator. So yes for NSArrays, no for NSSets and NSDictionarys