How to loop through arrays - ios

Now I loop through one Array at once and calculate distance like this:
- (void)calculateDistance
{
ann = [dict objectForKey:#"Blue"];
for(int i = 0; i < [ann count]; i++) {
NSString *coordinates = [[ann objectAtIndex:i] objectForKey:#"Coordinates"];
double realLatitude = [[[coordinates componentsSeparatedByString:#","] objectAtIndex:1] doubleValue];
double realLongitude = [[[coordinates componentsSeparatedByString:#","] objectAtIndex:0] doubleValue];
// Calculating distance
CLLocation *pinLocation = [[CLLocation alloc]
initWithLatitude:realLatitude
longitude:realLongitude];
CLLocation *userLocation = [[CLLocation alloc]
initWithLatitude:mapView.userLocation.coordinate.latitude
longitude:mapView.userLocation.coordinate.longitude];
CLLocationDistance distance = [pinLocation distanceFromLocation:userLocation];
// Adding distance to dictionaries
if (distance > 1000) {
NSString *dist = [NSString stringWithFormat:#"%.2f km.", distance/1000];
NSMutableDictionary *inDict = [[NSMutableDictionary alloc] init];
inDict = [ann objectAtIndex:i];
[inDict setValue:dist forKey:#"Distance"];
}
else{
NSString *dist = [NSString stringWithFormat:#"%4.0f m.", distance];
NSMutableDictionary *inDict = [[NSMutableDictionary alloc] init];
inDict = [ann objectAtIndex:i];
[inDict setValue:dist forKey:#"Distance"];
}
}
}
My data structure is:
How to loop through all Array's at once? I have Array which contains all my Array's named "resultArray", but this code doesn't work:
ann = [dict objectForKey:resultArray];
NSLog(#"%#", resultArray);
2013-05-05 10:57:03.643 testApp[5708:907] (
Black,
Green,
Orange,
Blue,
Darkblue
)

I guess you want to enumerate through the keys stored in resultArray and calculate the distance and add that calculated values to it.
- (void)calculateDistance
{
//Enumerates through resultArray
for (NSString *key in resultArray) {
//ann array is considered as an instance of NSMutableArray
ann = dict[key];
for(int i = 0; i < [ann count]; i++) {
NSMutableDictionary *inDict = [ann[i] mutableCopy];
NSString *coordinates = inDict[#"Coordinates"];
NSArray *coordinateComponents = [coordinates componentsSeparatedByString:#","];
double realLatitude = [coordinateComponents[1] doubleValue];
double realLongitude = [coordinateComponents[0] doubleValue];
// Calculating distance
CLLocation *pinLocation = [[CLLocation alloc] initWithLatitude:realLatitude
longitude:realLongitude];
CLLocation *userLocation = [[CLLocation alloc]
initWithLatitude:mapView.userLocation.coordinate.latitude
longitude:mapView.userLocation.coordinate.longitude];
CLLocationDistance distance = [pinLocation distanceFromLocation:userLocation];
// Adding distance to dictionaries
if (distance > 1000) {
NSString *dist = [NSString stringWithFormat:#"%.2f km.", distance/1000];
[inDict setValue:dist forKey:#"Distance"];
}
else{
NSString *dist = [NSString stringWithFormat:#"%4.0f m.", distance];
[inDict setValue:dist forKey:#"Distance"];
}
//Inserting the modified values to the main array
[ann replaceObjectAtIndex:i withObject:inDict];
}
}
}

ann = [dict objectForKey:resultArray];
for(NSArray *colourArray in ann)
{
for(NSDictionary *itemDictionary in colourArray)
{
NSLog(#"Coordinates = %#",[itemDictionary objectForKey:#"Coordinates"]);
NSLog(#"Name = %#",[itemDictionary objectForKey:#"Name"]);
NSLog(#"Address = %#",[itemDictionary objectForKey:#"Address"]);
}
}
Hope it will help you .

Related

Do not add annotations repeated

I am inserting some annotations that are coming from a json server, but I wanted to check if the annotation is already on the map, if so, does not add it again. For they are being added on each other , have someone help me solve this problem?
my code:
// adiciona produtos ao mapa
- (void)adicionaAnnotationsNoMapa:(id)objetos{
NSMutableArray *annotationsPins = [[NSMutableArray alloc] init];
for (NSDictionary *annotationDeProdutos in objetos) {
CLLocationCoordinate2D location;
AnnotationMap *myAnn;
myAnn = [[AnnotationMap alloc] init];
location.latitude = [[annotationDeProdutos objectForKey:#"latitude"] floatValue];
location.longitude = [[annotationDeProdutos objectForKey:#"longitude"] floatValue];
myAnn.coordinate = location;
myAnn.title = [annotationDeProdutos objectForKey:#"name"];
myAnn.subtitle = [NSString stringWithFormat:#"R$ %#",[annotationDeProdutos objectForKey:#"price"]];
myAnn.categoria = [NSString stringWithFormat:#"%#", [annotationDeProdutos objectForKey:#"id_categoria"]];
myAnn.idProduto = [NSString stringWithFormat:#"%#", [annotationDeProdutos objectForKey:#"id"]];
[annotationsPins addObject:myAnn];
}
[self.mapView addAnnotations:annotationsPins];
}
You can iterate through annotations already on MkMapView and see if they are already there:
NSArray * annotations = [self.mapView.annotations copy];
for (NSDictionary *annotationDeProdutos in objetos)
{
// Check if annotation in annotations are duplicate of annotationDeProdutos.
// You can match using name.
}
Or the other way if you only want to show annotations from single server call:
[self.mapView removeAnnotations: self.mapView.annotations];
// Now add from JSON response.
You can do this for each of your annotations:
if(![self.mapView.annotations containsObject: myAnn]) {
[self.mapView addAnnotations: myAnn];
}
I solved the problem with this code :
// adiciona produtos ao mapa
- (void)adicionaAnnotationsNoMapa:(id)objetos{
NSMutableArray *annotationsPins = [[NSMutableArray alloc] init];
for (NSDictionary *annotationDeProdutos in objetos) {
CLLocationCoordinate2D location;
AnnotationMap *myAnn;
myAnn = [[AnnotationMap alloc] init];
location.latitude = [[annotationDeProdutos objectForKey:#"latitude"] floatValue];
location.longitude = [[annotationDeProdutos objectForKey:#"longitude"] floatValue];
myAnn.coordinate = location;
myAnn.title = [annotationDeProdutos objectForKey:#"name"];
myAnn.subtitle = [NSString stringWithFormat:#"R$ %#",[annotationDeProdutos objectForKey:#"price"]];
myAnn.categoria = [NSString stringWithFormat:#"%#", [annotationDeProdutos objectForKey:#"id_categoria"]];
myAnn.idProduto = [NSString stringWithFormat:#"%#", [annotationDeProdutos objectForKey:#"id"]];
if (self.mapView.annotations.count <1) {
[annotationsPins addObject:myAnn];
} else {
__block NSInteger foundIndex = NSNotFound;
[annotationsPins enumerateObjectsUsingBlock:^(AnnotationMap *annotation, NSUInteger idx, BOOL *stop) {
CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:location.latitude longitude:location.longitude];
CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude longitude:annotation.coordinate.longitude];
if ([loc1 distanceFromLocation:loc2] <= 1.0f) {
foundIndex = idx;
*stop = YES;
}
}];
if (foundIndex != NSNotFound) {
[annotationsPins addObject:myAnn];
}
}
}
[self.mapView addAnnotations:annotationsPins];
}

Only showing one pin on the map from my array

I am having trouble showing pins on a map loading coordinates, title and subtitle from parse.com.
Here is my code. Is there any logical wrong? I get only the third row in the db showing, instead of all five that I have at the parse.com.
for(int i = 0; i<objects.count; i++)
{
int raknare = 1;
raknare++;
PFObject *tempObject = [kundUppgifter objectAtIndex:raknare];
PFGeoPoint *geoPoint = [tempObject objectForKey:#"CLAT"];
PFGeoPoint *geoPoint2 = (PFGeoPoint *)geoPoint;
NSString *cname = #"CNAME";
NSString *ctown = #"CTOWN";
kundUppgifter = [[NSArray alloc] initWithArray:objects];
objects = [NSArray arrayWithObjects:cname,ctown,geoPoint,nil];
NSMutableArray * locations = [[NSMutableArray alloc]init];
Annotation * myAnn;
myAnn = [[Annotation alloc]init];
CLLocationCoordinate2D location;
double longitude;
double latitude;
latitude = geoPoint2.latitude;
longitude = geoPoint2.longitude;
location.latitude = latitude;
location.longitude = longitude;
geoPoint.latitude = latitude;
geoPoint.longitude = longitude;
myAnn.coordinate = location;
myAnn.title = [tempObject objectForKey:#"CNAME"];
myAnn.subtitle = [tempObject objectForKey:#"CTOWN"];
[locations addObject:myAnn];
[self.myMapView addAnnotations:locations];
NSLog(#"geopoint is a pfobject with latitude %f, and longitude %f kundnamn %#,stad %#,", latitude, longitude, cname, ctown);
NSLog(#"%#", cname);
NSLog(#"%#", objects);
}
}
}];
Happy if you can help!
for(int i = 0; i<objects.count; i++)
{
int raknare = 1;
raknare++;
PFObject *tempObject = [kundUppgifter objectAtIndex:raknare];
}
This code inside of your loop will make raknare == 2 every iteration of the loop. You want to use the i variable you set to pull from -objectAtIndex: like this
for(int i = 0; i<objects.count; i++)
{
// This gives you a different object each iteration of the loop
PFObject *tempObject = [kundUppgifter objectAtIndex:i];
}

Sorting Distance in UITableview based on current location

How can i sort the array based on distance from current location and show in tableview .when i use below code for sorting am not getting any proper results ,am getting the array with random distance.can any one guide me for solve this issue
-(void)sort_distance{
// Determine distance between current location and geofence location
[distance_array removeAllObjects];
NSMutableDictionary *dict=[[NSMutableDictionary alloc] init];
CLLocation *pinLocation;
CLLocation *userLocation;
for (int i=0; i<[self.geofences count]; i++) {
//dict =[self.geofences objectAtIndex:i];
CLLocationDegrees firstLat = [self.currentLatitude doubleValue];
CLLocationDegrees firstLong = [self.currentLongitude doubleValue];
CLLocationDegrees secondLat = [[[self.geofences objectAtIndex:i] objectForKey:#"lat"] doubleValue];
CLLocationDegrees secondLong = [[[self.geofences objectAtIndex:i] objectForKey:#"lon"] doubleValue];
pinLocation = [[CLLocation alloc]
initWithLatitude:secondLat
longitude:secondLong];
userLocation = [[CLLocation alloc]
initWithLatitude:firstLat
longitude:firstLong];
CLLocationDistance distance = [pinLocation distanceFromLocation:userLocation]/1000;
//current distance is NSNumber
CLLocationDistance kilometers = distance /1000;
// or you can also use this..
distanceString = [[NSString alloc] initWithFormat: #"%.1f Km", kilometers];
NSLog(#"sa: %#", distanceString);
[distance_array addObject:distanceString];
[dict setObject:[NSNumber numberWithDouble:distance] forKey:#"newdistance"];
}
NSLog(#"distance array: %#", distance_array);
// Sorting the Geofence-Location depends on distance from current location
NSSortDescriptor * sort = [[NSSortDescriptor alloc] initWithKey:#"newdistance" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sort];
sortedArray = [self.geofences sortedArrayUsingDescriptors:sortDescriptors];
}
My out put is
distance array: (
"0.2 Km",
"0.4 Km",
"0.2 Km",
"0.6 Km",
"0.7 Km",
"1.0 Km",
"0.3 Km"
)
Thanks in Advance,
Chandu.
-(void)sort_distance{
// Determine distance between current location and geofence location
[distance_array removeAllObjects];
NSMutableDictionary *dict=[[NSMutableDictionary alloc] init];
CLLocation *pinLocation;
CLLocation *userLocation;
for (int i=0; i<[self.geofences count]; i++) {
//dict =[self.geofences objectAtIndex:i];
CLLocationDegrees firstLat = [self.currentLatitude doubleValue];
CLLocationDegrees firstLong = [self.currentLongitude doubleValue];
CLLocationDegrees secondLat = [[[self.geofences objectAtIndex:i] objectForKey:#"lat"] doubleValue];
CLLocationDegrees secondLong = [[[self.geofences objectAtIndex:i] objectForKey:#"lon"] doubleValue];
pinLocation = [[CLLocation alloc]
initWithLatitude:secondLat
longitude:secondLong];
userLocation = [[CLLocation alloc]
initWithLatitude:firstLat
longitude:firstLong];
CLLocationDistance distance = [pinLocation distanceFromLocation:userLocation]/1000;
//current distance is NSNumber
CLLocationDistance kilometers = distance /1000;
// or you can also use this..
distanceString = [[NSString alloc] initWithFormat: #"%.1f km", kilometers];
NSLog(#"sa: %#", distanceString);
[distance_array addObject:distanceString];
[dict setObject:[NSNumber numberWithDouble:distance] forKey:#"newdistance"];
}
NSLog(#"distance array: %#", distance_array);
// Sorting the Geofence-Location depends on distance from current location
sortedArray = [distance_array sortedArrayUsingSelector:#selector(compare:)];
NSLog(#"%#",sortedArray);
}
CLLocationDistance is double type, while you are saving it as integer type. So you will loose some precision. Instead use `[NSNumber numberWithDouble:].
This will sort in ascending order, for descending order return NSOrderedAscending in place of NSOrderedDescending and vice-versa.
-(CLLocationDistance )distanceOfCurrentPosition:(CLLocation *)userLocation WithPosition:(NSDictionary *)postition{
CLLocationDegrees secondLat = [postition[#"lat"] doubleValue];
CLLocationDegrees secondLong = [postition[#"lon"] doubleValue];
CLLocation *pinLocation = [[CLLocation alloc]
initWithLatitude:secondLat
longitude:secondLong];
CLLocationDistance distance = [pinLocation distanceFromLocation:userLocation]/1000;
CLLocationDistance kilometers = distance /1000;
return kilometers;
}
-(void)sort_distance{
CLLocationDegrees firstLat = [self.currentLatitude doubleValue];
CLLocationDegrees firstLong = [self.currentLongitude doubleValue];
CLLocation *userLocation = [[CLLocation alloc]
initWithLatitude:firstLat
longitude:firstLong];
[_geofences sortUsingComparator:^NSComparisonResult(NSDictionary *position1, NSDictionary *position2) {
CLLocationDistance distanceWithPosition1 = [self distanceOfCurrentPosition:userLocation WithPosition:position1];
CLLocationDistance distanceWithPosition2 = [self distanceOfCurrentPosition:userLocation WithPosition:position2];
if (distanceWithPosition1> distanceWithPosition2) {
return NSOrderedDescending;
}else if(distanceWithPosition2 > distanceWithPosition1){
return NSOrderedAscending;
}else{
return NSOrderedSame;
}
}];
NSLog(#"Order :%#",_geofences);
}
Try these for sort your array
-(NSArray *)sortArray:(NSArray *)arrayForSort forKey:(NSString *)key
{
return [arrayForSort sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
if([obj1 isKindOfClass:[NSDictionary class]] && [obj2 isKindOfClass:[NSDictionary class]])
return [[obj1 objectForKey:key] compare:[obj2 objectForKey:key]];
return NSOrderedSame;
}];
}
Just call it your case
self.geofences = [self sortArray:self.geofences forKey:#"newdistance"];
Have a nice day :)

Can't set different value for different dictionary

I loop through NSDictionaries to calculate distance from user location to annotations like this:
CLLocation *pinLocation = [[CLLocation alloc]
initWithLatitude:realLatitude
longitude:realLongitude];
CLLocation *userLocation = [[CLLocation alloc]
initWithLatitude:mapView.userLocation.coordinate.latitude
longitude:mapView.userLocation.coordinate.longitude];
CLLocationDistance distance = [pinLocation distanceFromLocation:userLocation];
The result:
NSLog(#"Distance: %4.0f m.", distance);
2013-05-04 15:58:53.301 testApp[3194:907] Distance: 65758 m.
2013-05-04 15:58:53.304 testApp[3194:907] Distance: 91454 m.
2013-05-04 15:58:53.308 testApp[3194:907] Distance: 248726 m.
2013-05-04 15:58:53.310 testApp[3194:907] Distance: 297228 m.
2013-05-04 15:58:53.313 testApp[3194:907] Distance: 163058 m.
Then I try to add distance for dictionaries in array
NSString *dist = [NSString stringWithFormat:#"%4.0f m.", distance];
[ann setValue:dist forKey:#"Distance"];
But it add only last distance (Distance: 163058 m.) for all dictionaries.
How can I set different value for different dictionary?
EDIT: My loop
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"blueKey"])
{
ann = [dict objectForKey:#"Blue"];
[resultArray addObject:#"Blue"];
for(int i = 0; i < [ann count]; i++) {
NSString *coordinates = [[ann objectAtIndex:i] objectForKey:#"Coordinates"];
double realLatitude = [[[coordinates componentsSeparatedByString:#","] objectAtIndex:1] doubleValue];
double realLongitude = [[[coordinates componentsSeparatedByString:#","] objectAtIndex:0] doubleValue];
MyAnnotation *myAnnotation = [[MyAnnotation alloc] init];
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = realLatitude;
theCoordinate.longitude = realLongitude;
myAnnotation.coordinate=CLLocationCoordinate2DMake(realLatitude,realLongitude);
myAnnotation.title = [[ann objectAtIndex:i] objectForKey:#"Name"];
myAnnotation.subtitle = [[ann objectAtIndex:i] objectForKey:#"Address"];
myAnnotation.icon = [[ann objectAtIndex:0] objectForKey:#"Icon"];
[mapView addAnnotation:myAnnotation];
[annotations addObject:myAnnotation];
// Calculating distance
CLLocation *pinLocation = [[CLLocation alloc]
initWithLatitude:realLatitude
longitude:realLongitude];
CLLocation *userLocation = [[CLLocation alloc]
initWithLatitude:mapView.userLocation.coordinate.latitude
longitude:mapView.userLocation.coordinate.longitude];
CLLocationDistance distance = [pinLocation distanceFromLocation:userLocation];
// NSLog(#"Distance: %4.0f m.", distance);
NSString *dist = [NSString stringWithFormat:#"%4.0f m.", distance];
[ann setValue:dist forKey:#"Distance"];
}
}
You can Add all the Values in some Array and then you can use it to save in different Dictionaries.
After this Line :
// NSLog(#"Distance: %4.0f m.", distance);
Add :
NSString *dist = [NSString stringWithFormat:#"%4.0f m.", distance];
NSMutableDictionary *inDict = [[NSMutableDictionary alloc] init];
inDict = [ann objectAtIndex:i];
[inDict setValue:dist forKey:#"Distance"];

How to limit load of Array depending on switch position

I load my annotations from plist and loop categories
NSMutableArray *annotations = [[NSMutableArray alloc]init];
NSString *path = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
for(path in dict){
NSString *theCategory;
theCategory = [NSString stringWithFormat:#"%#", path];
NSLog(#"%#", path);
NSArray *ann = [dict objectForKey:theCategory];
for(int i = 0; i < [ann count]; i++) {
NSString *coordinates = [[ann objectAtIndex:i] objectForKey:#"Coordinates"];
double realLatitude = [[[coordinates componentsSeparatedByString:#","] objectAtIndex:1] doubleValue];
double realLongitude = [[[coordinates componentsSeparatedByString:#","] objectAtIndex:0] doubleValue];
MyAnnotation *myAnnotation = [[MyAnnotation alloc] init];
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = realLatitude;
theCoordinate.longitude = realLongitude;
myAnnotation.coordinate=CLLocationCoordinate2DMake(realLatitude,realLongitude);
myAnnotation.title = [[ann objectAtIndex:i] objectForKey:#"Name"];
myAnnotation.subtitle = [[ann objectAtIndex:i] objectForKey:#"Address"];
myAnnotation.icon = [[ann objectAtIndex:0] objectForKey:#"Icon"];
[mapView addAnnotation:myAnnotation];
[annotations addObject:myAnnotation];
}
}
Then I have an switch in my settings
- (IBAction)saveSwitch:(id)sender
{
NSUserDefaults *defs1 = [NSUserDefaults standardUserDefaults];
[defs1 setBool: blackSwitch.on forKey: #"blackKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
I need to limit display of annotations from specific category by this switch. How it can be done, if I loop categories?
Inside your first loop, do this:
for(NSString *category in dict){
if ([category isEqualToString:#"Whatever"]) {
//continue?
NSArray *ann = [dict objectForKey:category];
BOOL blackKeyStatus = [[NSUserDefaults standardUserDefaults]boolForKey:#"blackKey"];
if (blackKeyStatus) {
//switch ON
//act appropriatelyForOnValue
//begin Loop 2 here?
} else {
//switch OFF
//act appropriately
}
} else {
//do something else?
}
If you're needing to test for a specific condition, do whatever is necessary to identify if that condition is met.

Resources