Do not add annotations repeated - ios

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];
}

Related

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 an array for UITableView

I have a function which prepares data for my UITableView:
- (void) SearchFromMyPosition {
TitleLabelSort = [[NSMutableArray alloc] init];
DistanceLabelSort = [[NSMutableArray alloc] init];
TagValueSort = [[NSMutableArray alloc] init];
DistanceUnitSort = [[NSMutableArray alloc] init];
LatArraySort = [[NSMutableArray alloc] init];
LngArraySort = [[NSMutableArray alloc] init];
// loading
[activityIndicatorObject startAnimating];
NSNumber *latNr1 = [[NSUserDefaults standardUserDefaults] valueForKey:#"api_lat"];
NSNumber *lngNr1 = [[NSUserDefaults standardUserDefaults] valueForKey:#"api_lng"];
double lat1 = [latNr1 doubleValue];
double lng1 = [lngNr1 doubleValue];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray *array = [APIConnection GetDataFromUrlAuth];
dispatch_async(dispatch_get_main_queue(), ^{
for (NSString *item in array) {
NSArray *coords = [[[array valueForKey:item] valueForKey:#"location"] componentsSeparatedByString:#"|"];
double lat2 = [[coords objectAtIndex:0] doubleValue];
double lng2 = [[coords objectAtIndex:1] doubleValue];
CLLocation *oldLocation = [[CLLocation alloc] initWithLatitude:lat1 longitude:lng1];
CLLocation *newLocation = [[CLLocation alloc] initWithLatitude:lat2 longitude:lng2];
CLLocationDistance meters = [newLocation distanceFromLocation:oldLocation];
[LatArraySort addObject:[NSString stringWithFormat:#"%f",lat2]];
[LngArraySort addObject:[NSString stringWithFormat:#"%f",lng2]];
[TitleLabelSort addObject:[[array valueForKey:item] valueForKey:#"name"]];
[DistanceLabelSort addObject:[NSString stringWithFormat:#"%f",meters]];
[TagValueSort addObject:item];
[self.myTableView reloadData];
[activityIndicatorObject stopAnimating];
}
});
});
}
This works but I need to sort results by DistanceLabelSort
For sorting CoreData results I use below function and works fine:
- (void) SetTableData {
TitleLabel = [[NSMutableArray alloc] init];
DistanceLabel = [[NSMutableArray alloc] init];
TagValue = [[NSMutableArray alloc] init];
DistanceUnit = [[NSMutableArray alloc] init];
LatArray = [[NSMutableArray alloc] init];
LngArray = [[NSMutableArray alloc] init];
// sorting
NSArray *sortedArray = [DistanceLabelSort sortedArrayUsingComparator:^(NSString *str1, NSString *str2) {
return [str1 compare:str2 options:NSNumericSearch];
}];
NSString *sortIdentStr = [[NSString alloc] init];
unsigned long sortIdent;
NSMutableArray *arrayUnit = [[NSMutableArray alloc] init];
for (int i = 0; i < sortedArray.count; i++) {
sortIdentStr = [sortedArray objectAtIndex:i];
sortIdent = [DistanceLabel indexOfObject:sortIdentStr];
arrayUnit = [self unitStr:sortIdentStr];
[TitleLabel addObject:[TitleLabelSort objectAtIndex:sortIdent]];
[TagValue addObject:[TagValueSort objectAtIndex:sortIdent]];
[LatArray addObject:[LatArraySort objectAtIndex:sortIdent]];
[LngArray addObject:[LngArraySort objectAtIndex:sortIdent]];
[DistanceLabel addObject:[arrayUnit objectAtIndex:0]];
[DistanceUnit addObject:[arrayUnit objectAtIndex:1]];
[self.myTableView reloadData];
[activityIndicatorObject stopAnimating];
}
}
But if I try use this for sorting data from external api function SetTableData is done before I get results from external api.
Finally I found solution and maybe this will be helpful for others:
I added function which checks if the task is done:
- (void)SearchFromMyPositionWithSuccess:(void (^)(void))successHandler failure:(void (^)(void))failureHandler {
TitleLabelSort = [[NSMutableArray alloc] init];
DistanceLabelSort = [[NSMutableArray alloc] init];
TagValueSort = [[NSMutableArray alloc] init];
DistanceUnitSort = [[NSMutableArray alloc] init];
LatArraySort = [[NSMutableArray alloc] init];
LngArraySort = [[NSMutableArray alloc] init];
// loading
[activityIndicatorObject startAnimating];
NSNumber *latNr1 = [[NSUserDefaults standardUserDefaults] valueForKey:#"api_lat"];
NSNumber *lngNr1 = [[NSUserDefaults standardUserDefaults] valueForKey:#"api_lng"];
double lat1 = [latNr1 doubleValue];
double lng1 = [lngNr1 doubleValue];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray *array = [APIConnection GetDataFromUrlAuth];
dispatch_async(dispatch_get_main_queue(), ^{
int i = 0;
for (NSString *item in array) {
i++;
NSArray *coords = [[[array valueForKey:item] valueForKey:#"location"] componentsSeparatedByString:#"|"];
double lat2 = [[coords objectAtIndex:0] doubleValue];
double lng2 = [[coords objectAtIndex:1] doubleValue];
CLLocation *oldLocation = [[CLLocation alloc] initWithLatitude:lat1 longitude:lng1];
CLLocation *newLocation = [[CLLocation alloc] initWithLatitude:lat2 longitude:lng2];
CLLocationDistance meters = [newLocation distanceFromLocation:oldLocation];
[LatArraySort addObject:[NSString stringWithFormat:#"%f",lat2]];
[LngArraySort addObject:[NSString stringWithFormat:#"%f",lng2]];
[TitleLabelSort addObject:[[array valueForKey:item] valueForKey:#"name"]];
[DistanceLabelSort addObject:[NSString stringWithFormat:#"%f",meters]];
[TagValueSort addObject:item];
if (i == array.count) {
successHandler();
}
[activityIndicatorObject stopAnimating];
}
});
});
}
And wait for success in this function:
-(void) SearchFromMyPosition {
[self SearchFromMyPositionWithSuccess: ^{
[self SetTableData];
NSLog(#"success");
} failure:^{
NSLog(#"failure");
}];
}
This solves my case :)

Map Annotations Displayed on Date

I have a map that displays an array of annotations. These annotations are all called from a plist and each have a date at which they occur. I would like these annotations to display only on the date that they happen, however I have no clue how to approach this. Any help would be much appreciated.
for (NSString *dateString in contentArray) {
[[NSUserDefaults standardUserDefaults] stringForKey:#"Date"];
}
This is the little bit of code I have written in but it does not solve anything for me.
EDIT:
Here is the code that calls the annotations generally.
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden = YES;
indexValue = 0;
NSString* plistPath = [[NSBundle mainBundle] pathForResource:#"mapAddress" ofType:#"plist"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
NSString *strID = [NSString stringWithFormat:#"%d",intID];
NSLog(#"array : %#",[dict objectForKey:strID]);
[contentArray removeAllObjects];
[contentArray addObjectsFromArray:[dict objectForKey:strID]];
[contentArray retain];
[self zoomToUserLocation:mapViewuno.userLocation];
}
- (void)zoomToUserLocation:(MKUserLocation *)userLocation
{
if (!userLocation)
return;
MKCoordinateRegion region;
region.center = userLocation.location.coordinate;
region.span = MKCoordinateSpanMake(.5, .5);
region = [mapViewuno regionThatFits:region];
[mapViewuno setRegion:region animated:YES];
counter = 0;
[mapViewuno removeAnnotations:mapViewuno.annotations];
if([contentArray count] != 0)
{
for(indexValue = 0; indexValue<[contentArray count];indexValue++)
{
FirstAnnotation *obj=[[FirstAnnotation alloc]init];
obj.latitude = [[[contentArray objectAtIndex:indexValue] objectForKey:#"lattitude"] floatValue];
obj.longitude = [[[contentArray objectAtIndex:indexValue] objectForKey:#"Longitude"] floatValue];
obj.titleName=[[contentArray objectAtIndex:indexValue] objectForKey:#"Title"];
obj.Address = [[contentArray objectAtIndex:indexValue] objectForKey:#"Address"];
obj.Phone = [[contentArray objectAtIndex:indexValue] objectForKey:#"Phone"];
obj.intTag = indexValue;
[mapViewuno addAnnotation:obj];
}
if ([mapViewuno.annotations count] == 0) return;
// [self.mapView setRegion:newRegion animated:YES];
}
}

How to loop through arrays

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 .

Why am I unable to remove my annotations from mapview?

Why am I unable to remove my annotations from mapview?
My code:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self becomeFirstResponder];
NSMutableArray *annotations = [[NSMutableArray alloc]init];
NSString *path = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"blackKey"])
{
NSLog(#"Black is on");
NSArray *ann = [dict objectForKey:#"Category1"];
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"];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"blackKey"])
{
NSLog(#"Black is on");
[mapView addAnnotation:myAnnotation];
[annotations addObject:myAnnotation];
} else
{
NSLog(#"Black is off");
[self.mapView removeAnnotation:myAnnotation];
}
}
}
else
{
//Do nothing
}
}
[self.mapView removeAnnotation:myAnnotation]; does not work for me
There is nothing to remove. You create the annotation, and then based off the check for blackKey, you EITHER add or remove it. But when you remove it, you never added it prior to that.

Resources