Search code examples
iphoneobjective-ciosautomatic-ref-countingcllocation

CLLocation causing EXC_BAD_ACCESS


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!


Solution

  • __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.