3

I have been working on an iPhone app, where-in i have list of users in a NSMutableArray like below.

myMutableArray: (
    {
        FirstName = Getsy;
        LastName = marie;
        Latitude = "30.237314";
        Longitude = "-92.461008";
    },
    {
        FirstName = Angel;
        LastName = openza;
        Latitude = "30.260329";
        Longitude = "-92.450414";
    },
    {
        FirstName = Sara;
        LastName = Hetzel;
        Latitude = "30.2584499";
        Longitude = "-92.4135357";
    }
)

I need to sort users based on the location who is nearby to my location by calculating latitude and longitude. I am not able to achieve this till now. Could someone help me on giving some samples?

UPDATED: I am trying like below as per Mr.sch suggested. Please check my updated code. Is it fine?.

    NSArray *orderedUsers = [myMutableArray sortedArrayUsingComparator:^(id a,id b) {
    NSArray *userA = (NSArray *)a;
    NSArray *userB = (NSArray *)b;
    CGFloat aLatitude = [[userA valueForKey:@"Latitude"] floatValue];
    CGFloat aLongitude = [[userA valueForKey:@"Longitude"] floatValue];
    CLLocation *participantALocation = [[CLLocation alloc] initWithLatitude:aLatitude longitude:aLongitude];

    CGFloat bLatitude = [[userA valueForKey:@"Latitude"] floatValue];
    CGFloat bLongitude = [[userA valueForKey:@"Longitude"] floatValue];
    CLLocation *participantBLocation = [[CLLocation alloc] initWithLatitude:bLatitude longitude:bLongitude];

    CLLocation *myLocation = [[CLLocation alloc] initWithLatitude:locationCoordinates.latitude longitude:locationCoordinates.longitude];

    CLLocationDistance distanceA = [participantALocation distanceFromLocation:myLocation];
    CLLocationDistance distanceB = [participantBLocation distanceFromLocation:myLocation];
    if (distanceA < distanceB) {
        return NSOrderedAscending;
    } else if (distanceA > distanceB) {
        return NSOrderedDescending;
    } else {
        return NSOrderedSame;
    }
}];

Thank you!

Getsy
  • 4,887
  • 16
  • 78
  • 139

5 Answers5

9
NSArray *orderedUsers = [users sortedArrayUsingComparator:^(id a,id b) {
     User *userA = (User *)a;
     User *userB = (User *)b;
     CLLocationDistance distanceA = [userA.location getDistanceFromLocation:myLocation];
     CLLocationDistance distanceB = [userB.location getDistanceFromLocation:myLocation];
     if (distanceA < distanceB) {
         return NSOrderedAscending
     } else if (distanceA > distanceB) {
         return NSOrderedDescending;
     } else {
         return NSOrderedSame;
     }
}];
sch
  • 27,436
  • 3
  • 68
  • 83
  • Hi, OK..What would be (User *)a, (User *)b in my case. I am having array of data. – Getsy Feb 16 '12 at 17:34
  • **a** and **b** are the two objects being compared. So you should have to find a way to access the location in each object, but that depends on the type of objects you did put on your array. – sch Feb 16 '12 at 17:43
  • OK.. I have two questions, 1. 'getDistanceFrom' is nothing but 'distanceFromLocation' ? 2. As i have the data in an NSMuableArray, do you think, this code will go through all each array in it? (or) I have to add any for loop inside? – Getsy Feb 16 '12 at 17:52
  • 1
    Yes you are right. **getDistanceFrom** should be **distanceFromLocation**. And concerning the second question, you don't have to make a for loop, **sortedArrayUsingComparator** will go through all items and return a sorted array. – sch Feb 16 '12 at 18:10
  • OK, then here is my question, i have a mutablearray then how can i give userB if i can't loop it (or) something like userB = [mymutablearray objectAtIndex:i] ? – Getsy Feb 16 '12 at 18:24
  • **userA = a;** and **userB = b;**. In fact it's ** sortedArrayUsingComparator** will be (kind of) looping through the array and execute the code in the block (**^(id a, id b) {...}**) for a pair of two items **a** and **b** from the array. – sch Feb 16 '12 at 18:43
  • Please check my updated code, i copied in my question. Is it fine? – Getsy Feb 16 '12 at 19:01
3

First thing, you will need to calculate the distance between your current location and the location of each other user.

Talking mathematically, here is a Wolfram|Alpha example

Now "programmatic-ally", you can use CLLocation class, here is an example:

(CLLocationDistance)getDistanceFrom:(const CLLocation *)location

But first you will need to create the location object from your Latitude and Longitude. You can use:

(id)initWithLatitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude
mohdajami
  • 9,604
  • 3
  • 32
  • 53
  • Thank you very much! How can i iterate through all users and compare their locations with my current location and sorted out? – Getsy Feb 16 '12 at 09:02
  • You can iterate over all objects using a normal `for loop` and use the method: [array objectAtIndex:theIndex]; – mohdajami Feb 16 '12 at 09:06
  • Ya, but iteration meaning, i need to sorted out. – Getsy Feb 16 '12 at 10:19
1

You can calculate the distance (geographical, not flat plane!) between your position and each of these items' positions and order by that value.

Alexander
  • 8,117
  • 1
  • 35
  • 46
  • Hi, Thank you for the reply. Not even calculation, i would like to know also how can i iterate through all the users and achieve this. – Getsy Feb 16 '12 at 08:51
0
- (void)viewDidLoad {
    [super viewDidLoad];
// This Array Taken Globally
List_of_locationsArray =[[NSMutableArray alloc]initWithObjects:
  @{@"latitude" : @"17.415045",@"logitude":@"78.421424"} ,@{@"latitude" : @"17.415045",@"logitude":@"78.421424"},@{@"latitude" : @"17.415045",@"logitude":@"78.421424"},@{@"latitude" : @"17.415045",@"logitude":@"78.421424"},@{@"latitude" : @"17.415045",@"logitude":@"78.421424"}
 ,nil];

}

-(void)sortingLocationsArray{
//    CLLocation* currentLocation =[[CLLocation alloc]initWithLatitude:[currentLatitude doubleValue] longitude:[currentLogitude doubleValue]];
      CLLocation* currentLocation =[[CLLocation alloc]initWithLatitude: currentLatitudeHere longitude:CurrentLogHere];

   NSMutableArray* tempLocationsArr = [[NSMutableArray alloc]initWithCapacity:[locationsArray count]];
    for (int i=0; i<[locationsArray count]; i++) {
        CLLocationDegrees latValue = [[locationsArray[i] objectForKey:@"latitude"] doubleValue];
        CLLocationDegrees longValue = [[locationsArray[i] objectForKey:@"logitude"] doubleValue];
        CLLocation* location = [[CLLocation alloc]initWithLatitude:latValue longitude:longValue];
        [tempLocationsArr addObject:location];

        NSArray* sortLocationArry = [tempLocationsArr sortedArrayUsingComparator:^NSComparisonResult(CLLocation* location1, CLLocation* location2) {
            CLLocationDistance distA = [location1 distanceFromLocation:currentLocation];
            CLLocationDistance distB = [location2 distanceFromLocation:currentLocation];
            if (distA < distB) {
                return NSOrderedAscending;
            } else if ( distA > distB) {
                return NSOrderedDescending;
            } else {
                return NSOrderedSame;
            }
        }];

      //ArrayAfterSorting is another mutable Array to Store Sorting Data
        [ArrayAfterSorting removeAllObjects];
        [sortLocationArry enumerateObjectsUsingBlock:^(CLLocation* location, NSUInteger idx, BOOL *stop) {
            NSMutableDictionary *tempDict = [[NSMutableDictionary alloc]init];
            [tempDict setObject:[NSString stringWithFormat:@"%f",location.coordinate.latitude] forKey:@"latitude"];
            [tempDict setObject:[NSString stringWithFormat:@"%f",location.coordinate.longitude] forKey:@"logitude"];
            [ArrayAfterSorting addObject:tempDict];


        }];
     NSLog(@"sortedArray : %@", ArrayAfterSorting);
    }

}
Sankar
  • 1
  • 2
-1
You may solve your problem in following way
1)Firstly store all above values in separate array Like latArray ,longArray,nameArray
2)Now get the distance between location(longArray,latArray) from your current location.
Then store these distances in separate Array(distanceArray).

//getDistance Between currentLocation and desired Location
-(void *)getDistanceFromCurrentLocation{  
for(int val=0;val<[latArray count];val++){
NSString *dis_From_Current_Location;
dis_From_Current_Location =nil;

CGFloat str_Longitude=[[defaults objectForKey:@"long"]floatValue];
CGFloat str_Latitude=[[defaults objectForKey:@"lati"]floatValue]; 
   //Suppose this is your current location 

CGFloat lat1= [[latArray objectAtIndex:val]floatValue];
    //these array for lat
CGFloat long1=[[longArray objectAtIndex:val]floatValue];
    //these array for longArray
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:lat1 longitude:long1];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:str_Latitude longitude:str_Longitude];
CLLocationDistance dist=[location1 distanceFromLocation:location2];
NSLog(@"Distance i meters: %f", [location1 distanceFromLocation:location2]);
long long v = llabs(dist/1000);
dis_From_Current_Location=[NSString stringWithFormat:@"%lld km",v];
[location1 release];
[location2 release];
[distanceArray addObject: dis_From_Current_Location];
//distanceArray is Global NsMutableArray.

}
}

Now You should Apply sorting method(selection, bubble) fro sorting the distances.

One thing need to care is that when you sort the distanceArray please adjust values of nameArray as according to the distanceArray See Below code for sorting the distanceArray and adjust the nameArray's value.

-(void)getSoretdArray{
NSString * tempStr,*tempStr2;
for(int i=0;i<[distanceArray count]; i++){
    for(int j=i+1;j<[distanceArray count]; j++){
        if([distanceArray objectAtIndex:j]>[distanceArray objectAtIndex:j+1]){
            tempStr=[distanceArray objectAtIndex:j];
            NSString* str= [distanceArray objectAtIndex:j+1];
            [ distanceArray insertObject:str atIndex:j];
            [distanceArray insertObject:tempStr atIndex:j+1] ;
            //also change the name of corresponding location.
            //you have to adjust the stored names in namArray for storing names of Corresponding Distances 
            tempStr2=[nameArray objectAtIndex:j];
            NSString* str1= [nameArray objectAtIndex:j+1];
            [ nameArray insertObject:str1 atIndex:j];
            [nameArray insertObject:tempStr2 atIndex:j+1] ;


        }
    }
}

}

This will definitely work just try to use carefully
Kamar Shad
  • 6,089
  • 1
  • 29
  • 56
  • Thank you..But i just gave an example of four fields such as firstname, lastname, latitude and longitude. Actually i have around 20 fields in an array and there are around 50 such array in mutable array. – Getsy Feb 16 '12 at 18:45
  • No problem, you can follow above code for same.it'll work. And apart from this,if you really find that answer good as you requiring.then accept it or up Vote it. – Kamar Shad Feb 16 '12 at 18:51