distance from CurrentLocation to data from Plist File - iphone

I have a long list of places with Latitudes and Longitudes in a plist. I want to show a tableView of the places only within X distance of the user's current location. Is there a way to create objects from the lats & longs in the plist file so I can use 'distanceFromLocation'? More importantly, how do I get the array to only display the names with a distance from current less than X? I'm assuming I would need to make a series of objects from lats & longs in the plist, then do an objects in array if objects distanceFrom is less than X, correct?
Please help.
Here's where I am now: I get an error on the double clubLatitude line
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *clubArray = [NSArray arrayWithObjects:[self danceClubLocation], nil];
self.tableData = clubArray;
}
-(CLLocation *)danceClubLocation
{
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"plist"];
NSArray *array = [NSArray arrayWithContentsOfFile:plistPath];
NSEnumerator *e = [array objectEnumerator];
id object;
while ((object = [e nextObject])) {
double clubLatitude = [[array valueForKey:#"Latitude"] doubleValue];
double clubLongitude = [[array valueForKey:#"Longitude"] doubleValue];
CLLocation *clubLocation = [[CLLocation alloc] initWithLatitude:clubLatitude longitude:clubLongitude];
if ([clubLocation distanceFromLocation:myLocation]<=50) {
return clubLocation;
}
else return nil;
}
return nil;
}
-(CLLocation *)myLocation
{
CLLocation *location = [locationManager location];
CLLocationCoordinate2D coordinate = [location coordinate];
NSNumber *myLatitude = [NSNumber numberWithDouble:coordinate.latitude];
NSNumber *myLongitude = [NSNumber numberWithDouble:coordinate.longitude];
double myLatitudeD = [myLatitude doubleValue];
double myLongitudeD = [myLongitude doubleValue];
myLocation = [[CLLocation alloc]initWithLatitude:myLatitudeD longitude:myLongitudeD];
return myLocation;
}

As #DavidNeiss said, you have to iterate over the list (an NSArray with the plist as source) and it would be something like this:
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"latlong" ofType:#"plist"];
NSArray *array = [NSArray arrayWithContentsOfFile:plistPath];
NSEnumerator *e = [array objectEnumerator];
id object;
while (object = [e nextObject]) {
// do something with object
}
Then you can do what you want (removing what's far from the user or whatever).

Read in your plist, iterate over it to pull out ones within X distance and populate any array with them that will be the data source for your table view?

Related

Extracting Unique Objects from a Data Array

I want to add names in a data array only if the name does not previously exist in the data array. When I attempt to print these names, I do get repetitions. Is there a way to solve this?
-(NSMutableArray *)autoComplete
{
NSMutableArray *dataArray = [[NSMutableArray alloc] init];
NSString *url = [NSString stringWithFormat:#"%#45.25,-95.25&limit=100&client_id=Von0J4Bu6INiez5bGby2R&client_secret=50sUjSbg7dba8cQgtpdfr5Ns7wyYTqtmKpUU3khQ",kWSURL];
NSDictionary * returnDict = (NSDictionary *) [self callWebService:url];
if([returnDict objectForKey:#"success"])
{
NSArray *responceArray = [returnDict objectForKey:#"response"];
for (NSDictionary *dict in responceArray) {
placeDC *place = [[placeDC alloc]init];
NSDictionary *placeDict = (NSDictionary *)[dict objectForKey:#"place" ];
NSDictionary *loctionDict =(NSDictionary *)[dict objectForKey:#"loc"];
NSString * name =[placeDict objectForKey:#"name"];
NSString * stateFull =[placeDict objectForKey:#"stateFull"];
NSString * countryFull =[placeDict objectForKey:#"countryFull"];
NSString *latitude =[loctionDict objectForKey:#"lat"];
NSString *longitude = [loctionDict objectForKey:#"long"];
place.placeNmae=name;
place.countryFullName=countryFull;
place.stateFullName=stateFull;
NSLog(#"%# ",stateFull);
place.latitude=[latitude doubleValue];
place.longitude=[longitude doubleValue];
[dataArray addObject:place];
}
}
return dataArray;
}
First Check that is there any response from the Server side or not, to check response use NSLog() or Break Points.
if response is ok then put a the following check your code
if (![dataArray containsObject:#"Some Name"])
{
// add Object
}
You could add the name NSString to an NSSet and check in every cycle whether it contains it or not.
Inside your if you could write something like:
NSArray *responceArray = [returnDict objectForKey:#"response"];
NSSet *names = [[NSSet alloc] init];
for (NSDictionary *dict in responceArray) {
NSDictionary *placeDict = (NSDictionary *)[dict objectForKey:#"place" ];
NSString * name =[placeDict objectForKey:#"name"];
if (![names containsObject:name]) {
[names addObject:name];
placeDC *place = [[placeDC alloc]init];
NSDictionary *loctionDict =(NSDictionary *)[dict objectForKey:#"loc"];
NSString * stateFull =[placeDict objectForKey:#"stateFull"];
NSString * countryFull =[placeDict objectForKey:#"countryFull"];
NSString *latitude =[loctionDict objectForKey:#"lat"];
NSString *longitude = [loctionDict objectForKey:#"long"];
place.placeNmae=name;
place.countryFullName=countryFull;
place.stateFullName=stateFull;
NSLog(#"%# ",stateFull);
place.latitude=[latitude doubleValue];
place.longitude=[longitude doubleValue];
[dataArray addObject:place];
}
}
Hope this helps!
Do one thing, add your dict in another array and search in this array that data already exist or not,
[tempAry addObject: dict];
and before insertion
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", name];
NSArray *filteredArray = [tempAry filteredArrayUsingPredicate:predicate];
if ([filteredArray count] == 0)
{
[dataArray addObject:place];
}
else{
//Already exist
}
Why don't you create a separate dictionary, as an ivar or property of you class, for storing our required value, say it as :
NSMutableDictionary *uniqueValueDict=[NSMutableDictionary new];
And keep storing your required value and key as:
[uniqueValueDict setObject:stateFull forKey:uniqueValueDict];
Your work will be done.
This is the easiest solution that i have applied and this should get you going in picking up unique elements out of array.
NSArray * claimedOfferArray = [[NSArray alloc]initWithObjects:#"A",#"B",#"A",#"C",#"B" nil];
NSArray * distinctArray = [[NSArray alloc]init];
distinctArray =[[NSSet setWithArray:claimedOfferArray] allObjects];
This code will also work with NSMutableArray
Let me know if it works for you..:).

Add annotations to a MapView in a loop

I am trying to add some annotations to my mkMapView in this loop:
for (PFObject *fetchedCompany in companyArray)
{
Store *store = [[Store alloc] initWithObject:fetchedCompany];
[self loadStore:store];
[store release];
}
- (void) loadStore:(Store *) store {
CLLocationCoordinate2D location = [self getLocationFromAddressString:store.address];
MapViewAnnotation *mapAnnotation = [[MapViewAnnotation alloc] initWithTitle:store.name coordinate:location];
[self.indexMapView addAnnotation:mapAnnotation];
}
And this the getLocationFromAddressString method that convert the address to a location using google api:
-(CLLocationCoordinate2D) getLocationFromAddressString:(NSString*) addressStr {
NSString *urlStr = [NSString stringWithFormat:#"http://maps.google.com/maps/geo?q=%#&output=csv", [addressStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSError *error = nil;
NSString *locationStr = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlStr] encoding:NSUTF8StringEncoding error:&error];
NSArray *items = [locationStr componentsSeparatedByString:#","];
double lat = 0.0;
double lon = 0.0;
if([items count] >= 4 && [[items objectAtIndex:0] isEqualToString:#"200"]) {
lat = [[items objectAtIndex:2] doubleValue];
lon = [[items objectAtIndex:3] doubleValue];
}
else {
NSLog(#"Address, %# not found: Error %#",addressStr, [items objectAtIndex:0]);
}
CLLocationCoordinate2D location;
location.latitude = lat;
location.longitude = lon;
return location;
}
When I send just one location always it works perfectly, but when I add annotations in my loop sometimes some locations could not be recognized and I got the error from my NSLog:
Address, Vallgatan 3 GĂ–TEBORG not found: Error 620
The thing is I am pretty sure about the addresses because when I tried them without loop they worked. Do you know how can I solve the problem?
You've submitted too many queries and your request got rejected. See Geocoding API V2 docs.
620: G_GEO_TOO_MANY_QUERIES
"The given key has gone over the requests limit in the 24 hour period or has submitted too many requests in too short a period of time. If you're sending multiple requests in parallel or in a tight loop, use a timer or pause in your code to make sure you don't send the requests too quickly"

Geting value from NSMutableArray after using sortedArrayUsingDescriptors

I have made a NSDictionary HospitalDictionary which holds latitude,longitude and distances
NSMutableArray *HospitalArray = [NSMutableArray array];
NSDictionary *HospitalDictionary = [[NSDictionary alloc]init];
NSString *LATITUDE = #"latitude";
NSString *LONGITUDE = #"longitude";
NSString *DISTANCE = #"distance";
for (int i=0; i<=100; i++) {
// calculations for coordinates and distance are done ....
HospitalDictionary = [NSDictionary dictionaryWithObjectsAndKeys:latitude, LATITUDE,
longitude, LONGITUDE,[NSNumber numberWithInt:distanceInKm], DISTANCE, nil];
[HospitalArray addObject:HospitalDictionary];
{
Then data is short using following code
// These line are added to short the Dictionary added to Array List with the Key of Distance
NSSortDescriptor *distanceDescriptor = [[NSSortDescriptor alloc] initWithKey:DISTANCE ascending:YES];
id obj;
NSEnumerator * enumerator = [HospitalArray objectEnumerator];
NSArray *descriptors = [NSArray arrayWithObjects:distanceDescriptor, nil];
NSArray *sortedArray = [HospitalArray sortedArrayUsingDescriptors:descriptors];
enumerator = [sortedArray objectEnumerator];
// this will print out the shorted list for DISTANCE
while ((obj = [enumerator nextObject])) NSLog(#"%#", obj);
// this will return the object at index 1
NSLog(#"Selected array is %#",[sortedArray objectAtIndex:1]);
Output of this is -
2012-05-30 08:24:42.784 Hospitals[422:15803]
sorted array is
{
distance = 1;
latitude = "27.736221";
longitude = "85.330095";
}
I want to get only Latitude or Longitude for the ObjectAtIndex:1 for the sortedArray. How can i get the particular value ie. latitude out of sortedArray not the complete list.
To access a property/method of an object in an array, you can use something like this:
NSLog(#"Latitude for object at index 1 is %#",[[sortedArray objectAtIndex:1] latitude]);

NSString parsing

I need to parse this string into three different components:
Location: 1|#69.83623|#24.432223|#Cupertino, California
The value is stored in one NSString. I need it in three different strings. One string for latitude, one for longitude and one for location.
Any idea how I can do that?
Thanks!
You can use this method to get an array of different components:
NSArray *bits = [locationString componentsSeparatedByString: #"|#"];
Each item in the NSArray will be an NSString.
Try the following
NSString *location = #"1|#69.83623|#24.432223|#Cupertino, California";
NSArray *components = [location componentsSeparatedByString:#"|#"];
NSLog(#"%#",components);
float latitude = [[components objectAtIndex:1] floatValue];
float longitude = [[components objectAtIndex:2] floatValue];
NSString *loc = [components objectAtIndex:3];
NSString *t = #"Location: 1|#69.83623|#24.432223|#Cupertino, California";
NSArray *k = [t componentsSeparatedByString:#"|"];
NSLog(#"components %#", k);

NSString: fastes way of splitting

my question is a performance question.
I need to split a huge NSString into coordinates. The string has this format:
#"coordx,coordy coordx,coordy coordx,coordy (...)"
My method to parse this is:
-(NSMutableArray*) parsePath:(NSString*) pathString
{
// first split between the coordinates
NSArray* path = [pathString componentsSeparatedByString:#" "];
NSMutableArray* coords = [[NSMutableArray alloc] init];
static NSString *seperator = #",";
NSArray *coord;
for(NSString *coordString in path)
{
coord = [coordString componentsSeparatedByString:seperator];
Coordinate *c = [[Coordinate alloc]init];
c.x = [[coord objectAtIndex:0] intValue];
c.y = [[coord objectAtIndex:1] intValue];
[coords addObject:c];
[c release];
}
return coords;
}
So, is there any way to make this faster?
Thanks!
Sebastian
Using NSScanner is probably faster.
http://developer.apple.com/iphone/library/documentation/cocoa/reference/Foundation/Classes/NSScanner_Class/Reference/Reference.html