iPhone - remove pin annotations of map, but not mine - iphone

I use a MapView and I set annotations on it (purple pins) and my user location (which is a blue circle).
Because the purple pin annotations will move, I have to remove and set them new to the map.
I set it with:
CLLocationCoordinate2D coordinate;
coordinate.latitude = 49.2802;
coordinate.longitude = -123.1182;
NSUInteger count = 1;
for(int i = 0; i < 10; i++) {
CGFloat latDelta = rand()*.035/RAND_MAX - .02;
CGFloat longDelta = rand()*.03/RAND_MAX - .015;
CLLocationCoordinate2D newCoord = {coordinate.latitude+latDelta, coordinate.longitude+longDelta};
MyMapAnnotation* annotation = [[MyMapAnnotation alloc] initWithCoordinate:newCoord andID:count++];
[mapView addAnnotation:annotation];
[annotation release];
}
Before that, I do a
[mapView removeAnnotations:mapView.annotations];
but this line also remove my location with the blue point!
How could I do this without removing my location.
Thanks a lot in advance & Best Regards.

A very easy way to do this is to include this line before the loop where you remove the annotations:
self.mapView.showsUserLocation = NO;
and then after the loop, put the user location back in
self.mapView.showsUserLocation = YES;
EDIT: I just saw that you didn't loop through the locations to remove them. I'm not sure if this will work with the way you do it.

Related

Issue with drawing path over MapKit

I have created an application that constantly reads the current user coordinates and store them in a SQLite database.
I have a map that is displayed over the whole screen.
And now I want to draw a line over the map while the user moves.
I already created all this.
The problem is that I can't make it to be a 'live'. The Overlay is not updating.
This is the logic:
In ViewDidLoad I have
...
if (nil != self.routeLine) {
[self.mapView addOverlay:self.routeLine];
}
In a function that handle each new coordinates I have:
...
NSString* coordinate = [NSString stringWithFormat:#"%f,%f", thisLocation.longitude, thisLocation.latitude];
[self.paths addObject:coordinate];
MKMapPoint northEastPoint;
MKMapPoint southWestPoint;
// create a c array of points.
MKMapPoint* pointArr = malloc(sizeof(CLLocationCoordinate2D) * self.paths.count);
for(int idx = 0; idx < self.paths.count; idx++)
{
// break the string down even further to latitude and longitude fields.
NSString* currentPointString = [self.paths objectAtIndex:idx];
NSArray* latLonArr = [currentPointString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#","]];
CLLocationDegrees latitude = [[latLonArr objectAtIndex:1] doubleValue];
CLLocationDegrees longitude = [[latLonArr objectAtIndex:0] doubleValue];
// create our coordinate and add it to the correct spot in the array
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
MKMapPoint point = MKMapPointForCoordinate(coordinate);
// adjust the bounding box
// if it is the first point, just use them, since we have nothing to compare to yet.
if (idx == 0) {
northEastPoint = point;
southWestPoint = point;
}
else
{
if (point.x > northEastPoint.x)
northEastPoint.x = point.x;
if(point.y > northEastPoint.y)
northEastPoint.y = point.y;
if (point.x < southWestPoint.x)
southWestPoint.x = point.x;
if (point.y < southWestPoint.y)
southWestPoint.y = point.y;
}
pointArr[idx] = point;
}
// create the polyline based on the array of points.
self.routeLine = [MKPolyline polylineWithPoints:pointArr count:self.paths.count];
_routeRect = MKMapRectMake(southWestPoint.x, southWestPoint.y, northEastPoint.x - southWestPoint.x, northEastPoint.y - southWestPoint.y);
// clear the memory allocated earlier for the points
free(pointArr);
This is viewForOverlay delegate function:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKOverlayView* overlayView = nil;
if(overlay == self.routeLine)
{
//if we have not yet created an overlay view for this overlay, create it now.
if(nil == self.routeLineView)
{
self.routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine];
self.routeLineView.fillColor = [UIColor blueColor];
self.routeLineView.strokeColor = [UIColor blueColor];
self.routeLineView.lineWidth = 5;
}
overlayView = self.routeLineView;
}
return overlayView;
}
In viewDidLoad, the code calls addOverlay with self.routeLine which I assume is initially set to the previously-saved coordinates.
The map view adds the MKPoyline that routeLine points to into its internal list of overlays and draws the overlay.
Then, in the "function that handles each new coordinate", self.routeLine is changed to point to a new MKPolyline.
The reason the overlay view is not updated by the map is because the map view is still using the original MKPolyline that was passed to it when addOverlay was called.
Since MKPolyline itself is not mutable (it does not allow one to change the list of points/coordinates after creation), there are two main options:
Remove the existing overlay and add a new one with the updated coordinates. This is the simplest option. After setting self.routeLine to a new MKPolyline, do the following (for example):
[self.mapView removeOverlays:mapView.overlays];
self.routeLineView = nil;
[self.mapView addOverlay:self.routeLine];
The main drawback to this simple approach is that the overlay will seem to flicker if the updates are done frequently or if the overlay is large or complex.
The alternative is to create a custom overlay and overlay view that are mutable and enabling you to dynamically refresh the overlay more quickly and smoothly.
Fortunately, Apple has provided a sample app called Breadcrumb which does exactly that.
Maybe you just forgot to call [self.view setNeedsDisplay]?
UIView docs

MapView shows max 3 annotations

really strange problem here.
I add 4 annotations (or 15, or 20, I've tried a lot of times) and I only get 2 or max 3 of them showing on the map (random ones).
here is the source:
// [self showRealEstates];
CLLocationCoordinate2D theCoordinate1;
theCoordinate1.latitude = 37.786996;
theCoordinate1.longitude = -122.419281;
CLLocationCoordinate2D theCoordinate2;
theCoordinate2.latitude = 37.810000;
theCoordinate2.longitude = -122.477989;
CLLocationCoordinate2D theCoordinate3;
theCoordinate3.latitude = 37.760000;
theCoordinate3.longitude = -122.447989;
CLLocationCoordinate2D theCoordinate4;
theCoordinate4.latitude = 37.80000;
theCoordinate4.longitude = -122.407989;
MapAnnotationRealEstate* myAnnotation1=[[MapAnnotationRealEstate alloc] initWithCoordinate:theCoordinate1 andTitle:#"Rohan"];
MapAnnotationRealEstate* myAnnotation2=[[MapAnnotationRealEstate alloc] initWithCoordinate:theCoordinate2 andTitle:#"Vaibhav"];
MapAnnotationRealEstate* myAnnotation3=[[MapAnnotationRealEstate alloc] initWithCoordinate:theCoordinate3 andTitle:#"Rituraj"];
MapAnnotationRealEstate* myAnnotation4=[[MapAnnotationRealEstate alloc] initWithCoordinate:theCoordinate4 andTitle:#"Sahil"];
NSMutableArray * annotations = [[NSMutableArray alloc] init];
[annotations addObject:myAnnotation1];
[annotations addObject:myAnnotation2];
[annotations addObject:myAnnotation3];
[annotations addObject:myAnnotation4];
[mapView addAnnotations:annotations];
// [mapView addAnnotation:myAnnotation1];
// [mapView addAnnotation:myAnnotation2];
// [mapView addAnnotation:myAnnotation3];
// [mapView addAnnotation:myAnnotation4];
NSLog(#"annotations: %d", [mapView annotations].count);
The log at the end shows 2, or 3. Don't know what to do, simplified the example as much as I could to eliminate other factors, still getting this.
As We can see the lat/long of these two are pretty close. I believe all the annotations are plotted on map and you are just not able to see from the current zoomlevel.
CLLocationCoordinate2D theCoordinate1;
theCoordinate1.latitude = 37.786996;
theCoordinate1.longitude = -122.419281;
CLLocationCoordinate2D theCoordinate4;
theCoordinate4.latitude = 37.80000;
theCoordinate4.longitude = -122.407989;
They seems to be overlapped in mapview in zoomed out view.
Try zoom-in your map to max level & I believe you will see all 4 annotations.
or you can try by changing the lat/long of one of these annotations.

How to have multiple annotations on a mapview based on an array

The below code is what I have used so far, and it loops through every object in the array correctly, but when I try to make them all display on one map it only adds the last obeject in the array to the map, not all 20 or so I want to display.
self.clientTable = [ClientDatabase database].clientTable;
ClientTable *info = nil;
[_nameLabel setText:info.name];
[_stateLabel setText:info.state];
//change the string to doubles for the map GPS co-ordinates
double latDouble = [info.latMap doubleValue];
double longDouble = [info.longMap doubleValue];
NSLog(#"%d",[self.clientTable count]);
int countArray = [self.clientTable count];
for (int i=0;i<countArray;i++) {
info = [self.clientTable objectAtIndex:i];
info.uniqueId=i;
NSLog(#" i = %d ; id = %d %#",i, info.uniqueId, info.name);
//set up the map
[super viewDidLoad];
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
MKCoordinateRegion region = {{0.0,0.0},{0.0,0.0}};
region.center.latitude = latDouble;
region.center.longitude = longDouble;
region.span.longitudeDelta =0.02; //degrees of acuracy, most precise best for this time
region.span.latitudeDelta =0.02; //degrees of accuracy
[mapView setRegion:region animated:YES];
// set up the annotation point
AllMap *annotationPoint = [[AllMap alloc] init];
annotationPoint.title = info.name;
annotationPoint.subtitle = info.state;
annotationPoint.coordinate = region.center;
[mapView addAnnotation:annotationPoint];
annotationPoint.isAccessibilityElement=YES;
//show annotation by default
[mapView selectAnnotation:annotationPoint animated:YES];
[mapView setDelegate:self];
}
Sorry if the code is rubbishy, i'm new to iPhone programming.
Thanks in advance :D
It looks like you're calling [super viewDidLoad] inside your for loop, which is probably resetting the mapView's annotations array. This method should only be called once, so if you move it before the for statement you may get better results.
why are you setting up the map inside of the loop where you are creating the annotations?
here is an old blog posting, but it covers the basics and should get you back on track

iPhone MapKit - update annotations coordinates and map

I use this tutorial for integrating MapKit to my application:
http://iphonebcit.wordpress.com/iphone-map-kit-tutorial/
CLLocationCoordinate2D coordinate;
coordinate.latitude = 49.2802;
coordinate.longitude = -123.1182;
NSUInteger count = 1;
for(int i = 0; i < 10; i++) {
CGFloat latDelta = rand()*.035/RAND_MAX - .02;
CGFloat longDelta = rand()*.03/RAND_MAX - .015;
CLLocationCoordinate2D newCoord = {coordinate.latitude+latDelta, coordinate.longitude+longDelta};
MapDemoAnnotation* annotation = [[MapDemoAnnotation alloc] initWithCoordinate:newCoord andID:count++];
[mapView addAnnotation:annotation];
[annotation release];
}
and
- (MKAnnotationView *)mapView:(MKMapView *)mapViewLocal viewForAnnotation:(id <MKAnnotation>)annotation {
MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapViewLocal dequeueReusableAnnotationViewWithIdentifier:#"Pin"];
if(pinView == nil) {
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"Pin"];
pinView.pinColor = MKPinAnnotationColorPurple;
pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
} else {
pinView.annotation = annotation;
}
return pinView;
}
So the pins will set on the map randomly. In my application, the coordinates will change. How can I change the coordinates of the annotations, so they will be updated on the map?
Does anyone know?
At iPhone SDK 3.x you have to remove the pin annotations and set it again. That is not very nice if you have many annotations an your map.
I try to make it better so I ony display/renew my pin annotations which are on the screen. So if an user zoom in to New York, there won't be pin annotations in San Francisco or other than the user can't see. So the performance will be much better.
Perhaps in the future this would be possible. I hope so :-)
That tutorial is only for getting a map view to show, nothing else. You're going to need a bigger tutorial. I found this one useful:
http://blog.objectgraph.com/index.php/2009/04/02/iphone-sdk-30-playing-with-map-kit/
Probably what you'll need to do is to loop through all the annotations on the map, removing them, then loop through your data array, adding the annotations back again. You could be more clever about it and loop through the data array, checking if there's already a pin with the same latitude/longitude on the map, but that way gets more complicated.
Since I'm doing annotations at the moment I just made a quick test. You do get a compiler warning, so it might not be supported. But it works.
Make a custom MKAnnotation class so you can set the coordinate property to be writable:
#property (nonatomic, readwrite) CLLocationCoordinate2D coordinate;
Then at whatever event or interval you want, change the coordinate using something like this:
CLLocation *loc=[[CLLocation alloc] initWithLatitude:55.0 longitude:17.0];
annotation.coordinate=loc.coordinate;
[loc release];

Uncenter MkMapView

I am trying to "uncenter" the map view and remove all annotations. the reason for this is that the mapView will be used by different view controllers to display different annotations and locations. What's happening now is that i am using the "remove annotations" method and i removes them, but the map stays centered on the spot and thus when the new annotations come in, it does not move. Is there a way to reset the region and if so, what value do i reset it to. I tried nil, zero and some calculated value but "core animation" says they are all invalid. how do i get that to zoom out and back in on my new annotations?
here is some code
-(void)recenterMap {
NSArray *coordinates = [_mapView valueForKeyPath:#"annotations.coordinate"];
CLLocationCoordinate2D maxCoord = {-90.0f, -180.0f};
CLLocationCoordinate2D minCoord = {90.0f, 180.0f};
//NSLog(#"%#", [coordinates description]);
for (NSValue *value in coordinates) {
CLLocationCoordinate2D coord = {0.0f, 0.0f};
[value getValue: &coord];
if(coord.longitude > maxCoord.longitude) {
maxCoord.longitude = coord.longitude;
}
if(coord.latitude > maxCoord.latitude){
maxCoord.latitude = coord.latitude;
}
if(coord.longitude < minCoord.longitude){
minCoord.longitude = coord.longitude;
}
if(coord.latitude < minCoord.latitude){
minCoord.latitude = coord.latitude;
}
}
MKCoordinateRegion region = {{0.0f, 0.0f}, {0.0f, 0.0f}};
region.center.longitude = (minCoord.longitude + maxCoord.longitude) / 2.0;
region.center.latitude = (minCoord.latitude + maxCoord.latitude) / 2.0;
region.span.longitudeDelta = maxCoord.longitude - minCoord.longitude;
region.span.latitudeDelta = maxCoord.latitude - minCoord.latitude;
[_mapView setRegion: region animated: YES];
}
Thats the recenter methos i'm using
- (MKAnnotationView *)mapView: (MKMapView *)mapView viewForAnnotation: (id <MKAnnotation>)annotation{
MKAnnotationView *view = nil;
if(annotation != mapView.userLocation){
Annotation *schoolAnn = (Annotation*)annotation;
view = [self.mapView dequeueReusableAnnotationViewWithIdentifier:#"schoolLoc"];
if(nil == view){
view = [[[MKPinAnnotationView alloc] initWithAnnotation:schoolAnn reuseIdentifier:#"schoolLoc"]autorelease];
}
[(MKPinAnnotationView *)view setAnimatesDrop:YES];
[view setCanShowCallout:YES];
}
else {
[self recenterMap];
}
return view;
}
This "else" piece waits until the blue marble drops in then recenters the map. The problem i have with that part is that when i go back to the previous View Controller i remove all annotations, so when i come back in the User location (for some reason) does not pop back in. How do i get this to pop back in?
thanks in advance guys
Got the first part, made it zoom out again by just calling a function i made that set the region up to be over the US.
-(void)unCenterMap{
MKCoordinateRegion region2 = {{0.0f, 0.0f}, {0.0f, 0.0f}};
region2.center.longitude = (-98.151855); //coordinate for approximately the center of the US
region2.center.latitude = 39.402244;
region2.span.longitudeDelta = 3.0;
region2.span.latitudeDelta = 3.0;
[_mapView setRegion: region2 animated: YES];
}
The second part still baffles me, how do I get that location to pop in again?