Uncenter MkMapView - iphone

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?

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

Centering MKMapView on an annotation

Although the process for doing this is well documented, I am unable to solve this problem.
All I want to do is to take the coordinate at which I have just created an annotation and have the map zoom in and center on it. I followed this tutorial with some modifications:
http://maybelost.com/2011/01/a-basic-mapview-and-annotation-tutorial/
The MapViewAnnotation class consists of just a title and the coordinates.
_detailItem is simply an object that holds a name, latitude, and longitude as strings.
I have a basic map. I'm using a storyboard (so, ARC). I have coordinates. Here's my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
// Set some coordinates for our position
CLLocationCoordinate2D location;
double thisLat = [_detailItem.EventLat doubleValue];
double thisLong = [_detailItem.EventLong doubleValue];
location.latitude = (double)thisLat;
location.longitude = (double)thisLong;
// Add the annotation to our map view
MapViewAnnotation *newAnnotation = [[MapViewAnnotation alloc] initWithTitle:_detailItem.EventName andCoordinate:location];
[self.map addAnnotation:newAnnotation];
}
// When a map annotation point is added, zoom to it
- (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views
{
MKAnnotationView *annotationView = [views objectAtIndex:0];
id <MKAnnotation> mp = [annotationView annotation];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([mp coordinate], 1000, 1000);
[mv setRegion:region animated:YES];
[mv selectAnnotation:mp animated:YES];
}
Yeah. When I do this, the annotations shows up as expected, but the map doesn't center on it or zoom in. During debug, I found that didAddAnnotationViews isn't being called at all! Yet, I've clearly made an explicit call to addAnnotation.
Help?
didAddAnnotationViews isn't being called at all
In your viewDidLoad implementation, add this line:
self.map.delegate = self;
See if that changes things.

Crashed while removing the pin from mapview

I am working on MapView,on which I have two buttons.
1)centreButton:
this button drops the pin annotation at the centre of the current map.
when this button is pressed, I am storing the last annotation in a NSMutable array.
then remove the last annotation from mapview and drop one pin at the centre of map
Code I have done for this part is as follows:
function for dropping the pin
- (void)PinDropwithlatitude:(double)lat longitude:(double)longi droptitle:(NSString *)title
{
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = lat;
theCoordinate.longitude = longi;
MKCoordinateRegion region;
region.center.latitude = theCoordinate.latitude;
region.center.longitude = theCoordinate.longitude;
//Set Zoom level using Span
MKCoordinateSpan span;
span.latitudeDelta =0.005;
span.longitudeDelta =0.005;
region.span = span;
[MapView setRegion:region animated:YES];
SetLat =lat;
SetLong =longi;
DDAnnotation *annotation = [[[DDAnnotation alloc] initWithCoordinate:theCoordinate addressDictionary:nil] autorelease];
annotation.title = title;
annotation.subtitle = [NSString stringWithFormat:#"%f %f", annotation.coordinate.latitude, annotation.coordinate.longitude];
[MapView addAnnotation:annotation];
}
when I press centre button I am doing the following code and store last array in annotation.
-(IBAction)CenterPressed:(id)sender
{
//40.439631,-3.698273 -spain centre
[lastAnnotation addObjectsFromArray:MapView.annotations];
NSLog(#"last annotation array=%#",lastAnnotation);
for (id annotation in [MapView annotations])
{
if ([annotation isKindOfClass:[MKUserLocation class]])
{
continue;
}
[MapView removeAnnotation:annotation];
}
[self PinDropwithlatitude:SetLat longitude:SetLong
droptitle:NSLocalizedString(#"Title", nil)];
}
the log for the array is showing me the
last annotations you can see below::
last annotation array=(
"<+40.43963100,-3.69827300> +/- 0.00m",
"<+40.43923187,-3.68722200> +/- 0.00m",
"<+40.43792343,-3.67670774> +/- 0.00m",
"<+40.43772888,-3.66711617> +/- 0.00m"
)
2)UNDOButton: which removes the currently placed annotation and redrop the previous annotation, for that i have removed the annotaion from mapview, and redrop the annotation last annotation from array which i have maintained previously,using the code:
-(IBAction)undoPressed:(id)sender
{
if ([lastAnnotation count]>0)
{
int countAnn = [lastAnnotation count];
[MapView removeAnnotation:[lastAnnotation objectAtIndex:countAnn-1]];
//[MapView delete:[lastAnnotation objectAtIndex:countAnn-1]];
[lastAnnotation removeObjectAtIndex:countAnn-1];
double latitude = [[[lastAnnotation objectAtIndex:[lastAnnotation count]-1] annotation]coordinate].latitude;
double longitude = [[[lastAnnotation objectAtIndex:[lastAnnotation count]-1]annotation]coordinate].longitude;
NSLog(#"count = %d",[lastAnnotation count]);
[self PinDropwithlatitude:latitude longitude:longitude droptitle:NSLocalizedString(#"Title", nil)];
}
}
but when i press the undo button it crashes with the following error
-[DDAnnotation annotation]: unrecognized selector sent to instance 0x79b8f40
I don't get to know, where exactly the problem arises. can any one please help me to point out my mistake in the above code.
thanks
can you try
[lastAnnotation lastObject]
instead of
[[lastAnnotation objectAtIndex:[lastAnnotation count]-1]
like
[MapView removeAnnotation:[lastAnnotation lastObject]];
[lastAnnotation removeObject:[lastAnnotation lastObject]];

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 - remove pin annotations of map, but not mine

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.