10

I'm having a problem with isEqual:

The code:

 if (currentAnchor isEqual:currentBusiness.getCllLocation))
    {
        do a;
    }
    else
    {
        do b;
    }

currentanchor and currentbusiness.getCllocation are locations

But if they are the same, why is function b called? Is something wrong with my code?

Abizern
  • 146,289
  • 39
  • 203
  • 257
user4951
  • 32,206
  • 53
  • 172
  • 282

4 Answers4

27

I assume both of these objects are of type CLLocation, based on the name of getClLocation.

CLLocation doesn't have any specification on what its isEqual: method does, so it's likely just inheriting the implementation of NSObject, which simply compares the pointers of the objects. If you've got two distinct objects with identical data, that isEqual: implementation would return NO. And if you've got two distinct objects with just a slight variation in location, they definitely would not be equal.

You probably don't want isEqual: when comparing location objects. Rather, you probably want to use the distanceFromLocation: method on CLLocation. Something like this would be better:

CLLocationDistance distanceThreshold = 2.0; // in meters
if ([currentAnchor distanceFromLocation:currentBusiness.getCllLocation] < distanceThreshold)
{
  do a;
}
else
{
  do b;
}
BJ Homer
  • 48,806
  • 11
  • 116
  • 129
  • It is not quite right to compare only lat/lon of the CLLocation as it does have other properties too. So if the aim to compare location then it is fine, but if you are comparing two CLLocation objects by its properties you need to include others also. Like speed, accuracy, timetamp etc. – David Chelidze Oct 26 '22 at 16:58
2

It's been a while.

What I did is similar with BJ Homer. I just add this.

@interface CLLocation  (equal)
- (BOOL)isEqual:(CLLocation *)other;
@end

@implementation CLLocation  (equal)

- (BOOL)isEqual:(CLLocation *)other {


    if ([self distanceFromLocation:other] ==0)
    {
        return true;
    }
    return false;
}
@end

I was surprised I were the one asking this question :)

Felix Lamouroux
  • 7,414
  • 29
  • 46
user4951
  • 32,206
  • 53
  • 172
  • 282
  • i suggest to declare `other` as `id` to implement it safely – Zerho Sep 06 '13 at 18:09
  • 2
    It is most likely cheaper to simply test equality on the coordinate and to otherwise return super. `self.coordinate.latitude == other.coordinate.latitude && self.coordinate.longitude == other.coordinate.longitude` – Felix Lamouroux Apr 15 '14 at 21:57
  • You are overriding a method in a category. Which is a bad practice .you might get an unspecified behavior of this method. According to apple documentation "If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime. This is less likely to be an issue if you’re using categories with your own classes, but can cause problems when using categories to add methods to standard Cocoa or Cocoa Touch classes." – Ali Amin Jul 24 '14 at 09:33
  • I tried using `== 0`, I wonder why chosen answer is using '2.0` threshold. – Amr Lotfy Mar 20 '16 at 15:31
0

Swift 4.0 version:

let distanceThreshold = 2.0 // meters
if location.distance(from: CLLocation.init(latitude: annotation.coordinate.latitude,
                                           longitude: annotation.coordinate.longitude)) < distanceThreshold
{ 
    // do a
} else {
    // do b
}
Stunner
  • 12,025
  • 12
  • 86
  • 145
0

isEqual just check only objects not their content. you require to create your own method where you access the variables of object and check them for equality using == operator.

Jhaliya - Praveen Sharma
  • 31,697
  • 9
  • 72
  • 76
  • This is not true, isEqual is supposed to do just that, check the content's to determine if two objects are equal. Two objects are not equal if their properties are not the same. – Maciej Swic Jan 08 '15 at 09:33