0

This code works some of the time, but then sometimes crashes with a EXC_BAD_ACCESS error.

NSInteger compareDistance(id num1, id num2, void *context) 
{
    int rv;
    //cast parameters from general type
    CLLocation* location = (__bridge_transfer CLLocation *)context;
    Attraction* attr1 = num1;
    Attraction* attr2 = num2;

    //convert to CLLocation objects and calculate distance from user current
    CLLocation* locationAttr1 = 
    [[CLLocation alloc] initWithLatitude:attr1.latitude 
                               longitude:attr1.longitude];
    CLLocation* locationAttr2 = 
    [[CLLocation alloc] initWithLatitude:attr2.latitude 
                               longitude:attr2.longitude];
    CLLocationDistance distance1 = [locationAttr1 distanceFromLocation:location];
    CLLocationDistance distance2 = [locationAttr2 distanceFromLocation:location];

    //compare and rate
    if (distance1 < distance2)
        rv = NSOrderedAscending;
    else if (distance1 > distance2)
        rv = NSOrderedDescending;
    else
        rv = NSOrderedSame;

    return rv;
}

This is a compare function for ordering an NSMutableArray:

-(NSMutableArray *)getAttractionsByDistanceInCategory:(int)catID
{
    [self confirmAttractions];

    //set up array and context to prepare for sort
    NSMutableArray *attractionsToSort = [[NSMutableArray alloc] init];
    for (Attraction *a in attractions)
    {
        if ((catID < 0) || (catID >= 0 && a.category == catID))
            [attractionsToSort addObject:a];
    }

    CLLocation* currentLocation = 
        [[CLLocation alloc] initWithLatitude:usersLat longitude:usersLng];

    //conduct sort
    [attractionsToSort sortUsingFunction:compareDistance
                                 context:(__bridge_retained void *)currentLocation];

    return attractionsToSort;
}

Hmm. Do you think the problem could be ARC? I'm side-eyeing that __bridge_retained void * business.

Thanks in advance for any advice!

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Sabrina S
  • 337
  • 8
  • 21
  • 1
    Might want to consider turning on NSZombieEnabled. – Patrick Perini May 02 '12 at 03:05
  • Hmm, I tried this, and got this error: `-[CLLocation release]: message sent to deallocated instance 0x6ac2090`. `EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0`. Calculating coordinate distance by hand might be easier than this... – Sabrina S May 02 '12 at 03:21

1 Answers1

3

__bridge_transfer transfers ownership to the destination object, which is probably not what you want to do here, you don't want ownership of the context, because ARC will try and release it when it thinks you are done with it, and you don't want it to do that.

Basically, you don't want to transfer ownership anywhere, so just use __bridge in both cases, and it should work fine.

dreamlax
  • 93,976
  • 29
  • 161
  • 209
  • The compiler would not accept anything but `__bridge_transfer` there. It wouldn't accept `__bridge` and it wouldn't accept `__bridge_retain`. ETA: And of course it wouldn't accept simply passing `currentLocation` as is. – Sabrina S May 02 '12 at 03:39
  • Ooh, wait, scratch that, I thought you were referring to `__bridge_retained` in the calling function. Trying `__bridge`. – Sabrina S May 02 '12 at 03:42
  • Initial results are promising. :) Thanks for your suggestion. – Sabrina S May 02 '12 at 03:44