Plot pin does not point exact place on MKMapView - ios

- (void)viewDidLoad
{
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(foundTap:)];
tapRecognizer.numberOfTapsRequired = 1;
tapRecognizer.numberOfTouchesRequired = 1;
[self.myMapView addGestureRecognizer:tapRecognizer];
}
-(void)foundTap:(UITapGestureRecognizer *)recognizer
{
CGPoint point = [recognizer locationInView:self.myMapView];
CLLocationCoordinate2D tapPoint = [self.myMapView convertPoint:point toCoordinateFromView:self.view];
MKPointAnnotation *point1 = [[MKPointAnnotation alloc] init];
point1.coordinate = tapPoint;
[self.myMapView addAnnotation:point1];
}
I used above code to make pin point on MKMapView when i choose a place in MKMapView it does not point where i exactly touches.It goes little far where i touches.What is wrong with my code?.any help will be appreciated.thanks in advance.

Try changing the passed-in object to the locationInView: method to self.view:
-(void)foundTap:(UITapGestureRecognizer *)recognizer
{
CGPoint point = [recognizer locationInView:self.view];
CLLocationCoordinate2D tapPoint = [self.myMapView convertPoint:point toCoordinateFromView:self.view];
MKPointAnnotation *point1 = [[MKPointAnnotation alloc] init];
point1.coordinate = tapPoint;
[self.myMapView addAnnotation:point1];
}

I know the other answer is working for you, but I just wanted to show the proper way to use convertPoint:toCoordinateFromView:. Instead of passing it the container view, it should be passed the map view that the point is in:
CLLocationCoordinate2D tapPoint = [self.myMapView convertPoint:point
toCoordinateFromView:self.myMapView];
That saves swapping between views. Here's the full method:
-(void)foundTap:(UITapGestureRecognizer *)recognizer
{
CGPoint point = [recognizer locationInView:self.myMapView];
CLLocationCoordinate2D tapPoint = [self.myMapView convertPoint:point toCoordinateFromView:self.myMapView];
MKPointAnnotation *point1 = [[MKPointAnnotation alloc] init];
point1.coordinate = tapPoint;
[self.myMapView addAnnotation:point1];
}

Related

MkmapView: How to keep the map centered while the user zoom

I'm trying to implement the same map behaviour has Uber.
I would like to keep the map centered while the user zoom the map with a pinch or a double tap.
I tried implementing my own gesture recognizer but the result isn't great...
Does anyone got an idea of how to do it ?
Thanks !
For those interested in the solution i managed to do it.
First you need to add your gesture recognizer in the viewDidload
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:#selector(pinchOnMap:)];
[pinch setDelegate:self];
[pinch setDelaysTouchesBegan:YES];
[self.mapGestureContainer addGestureRecognizer:pinch];
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(zoomInGesture:)];
gestureRecognizer.delegate = self;
[gestureRecognizer setDelaysTouchesBegan:YES];
gestureRecognizer.numberOfTapsRequired = 2;
[self.mapGestureContainer addGestureRecognizer:gestureRecognizer];
Then implement the gesture function, it will handle the zoom based on the pinch scale. I added a small delay to avoid too much processing.
-(void) zoomInGesture:(UITapGestureRecognizer *) recognizer {
currentRegion = self.mapView.region;
currentSpan = self.mapView.region.span;
isZoomingWithDoubleTap = YES;
MKCoordinateRegion region = currentRegion;
MKCoordinateSpan span = currentSpan;
span.latitudeDelta = currentSpan.latitudeDelta / 2.3;
span.longitudeDelta = currentSpan.longitudeDelta / 2.3;
region.span = span;
[self.mapView setRegion:region animated:YES];
}
//Gesture used when the user pinch the area of the map
- (void) pinchOnMap:(UIPinchGestureRecognizer *) recognizer {
if (recognizer.state == UIGestureRecognizerStateBegan) {
isPinching = YES;
self.mapView.scrollEnabled = NO;
self.mapView.userInteractionEnabled = NO;
currentRegion = self.mapView.region;
currentSpan = self.mapView.region.span;
lastZoomTime = [[NSDate date] timeIntervalSince1970];
}
if (recognizer.state == UIGestureRecognizerStateEnded) {
isPinching = NO;
self.mapView.scrollEnabled = YES;
self.mapView.userInteractionEnabled = YES;
}
if (recognizer.state == UIGestureRecognizerStateChanged) {
if (([[NSDate date] timeIntervalSince1970] * 1000) - lastZoomTime >= 20) {
lastZoomTime = [[NSDate date] timeIntervalSince1970] * 1000;
MKCoordinateRegion region = currentRegion;
MKCoordinateSpan span = currentSpan;
span.latitudeDelta = currentSpan.latitudeDelta / recognizer.scale;
span.longitudeDelta = currentSpan.longitudeDelta / recognizer.scale;
region.span = span;
[self.mapView setRegion:region animated:NO];
}
}
}
In your map view delegate, do this
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
[mapView setCenterCoordinate:userLocation.location.coordinate animated:YES];
}

not able to add annotation to mapView iOS from a different method

I'm trying to add a annotation to the map from a different button method, however it doesn't show up. It doesn't give an error either.
Where as all the annotations which I have mentioned in the mapView method, they are being displayed.
-(void) testButton {
/// custom location coordinate
CLLocationCoordinate2D userLocationNew2 = CLLocationCoordinate2DMake(-80.050003, -13.416667);
// use that cusom coordinate
MKCoordinateRegion region2 = MKCoordinateRegionMakeWithDistance(userLocationNew2, 20000, 20000);
[mapView setRegion:[self.mapView regionThatFits:region2] animated:YES];
// Add an annotation
MKPointAnnotation *point2 = [[MKPointAnnotation alloc] init];
point2.coordinate = userLocationNew2;
point2.title = #"Check";
// point2.subtitle = #"Right here oooooo!!!";
[mapView addAnnotation:point2];
}
The other method
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
/// custom location coordinate
CLLocationCoordinate2D userLocationNew2 = CLLocationCoordinate2DMake(-73.050003, -13.416667);
// use that cusom coordinate
MKCoordinateRegion region2 = MKCoordinateRegionMakeWithDistance(userLocationNew2, 20000, 20000);
[self.mapView setRegion:[self.mapView regionThatFits:region2] animated:YES];
// Add an annotation
MKPointAnnotation *point2 = [[MKPointAnnotation alloc] init];
point2.coordinate = userLocationNew2;
point2.title = #"Basic";
}

How to Move MKCircleView at one position to another position in MKMapView?

I am Declare locations by using MkCircle Now I have to change Circle position one place to another place in MKMapView(Drag & Drop). how can i achieve this. Any help will be appreciated.
First, I'd suggest you have some class property to keep track of the overlay:
#property (nonatomic, weak) MKCircle *overlay;
Then, define a UIPanGestureRecognizer to perform the drag and drop:
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[self.mapView addGestureRecognizer:pan];
To make the gesture cancelable, you should import the following header:
#import <UIKit/UIGestureRecognizerSubclass.h>
And you need to write a handler for this gesture recognizer that adds an overlay for where you dragged and removes the old one (but cancels the gesture if it didn't start over the overlay):
- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
static CGPoint originalPoint;
if (gesture.state == UIGestureRecognizerStateBegan) {
CGPoint point = [gesture locationInView:gesture.view];
CLLocationCoordinate2D tapCoordinate = [self.mapView convertPoint:point toCoordinateFromView:gesture.view];
CLLocation *tapLocation = [[CLLocation alloc] initWithLatitude:tapCoordinate.latitude longitude:tapCoordinate.longitude];
CLLocationCoordinate2D originalCoordinate = [self.overlay coordinate];
CLLocation *originalLocation = [[CLLocation alloc] initWithLatitude:originalCoordinate.latitude longitude:originalCoordinate.longitude];
if ([tapLocation distanceFromLocation:originalLocation] > [self.overlay radius]) {
gesture.state = UIGestureRecognizerStateCancelled;
return;
}
else
originalPoint = [self.mapView convertCoordinate:originalCoordinate toPointToView:gesture.view];
}
if (gesture.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [gesture translationInView:gesture.view];
CGPoint newPoint = CGPointMake(originalPoint.x + translation.x, originalPoint.y + translation.y);
CLLocationCoordinate2D newCoordinate = [self.mapView convertPoint:newPoint toCoordinateFromView:gesture.view];
MKCircle *circle = [MKCircle circleWithCenterCoordinate:newCoordinate radius:[self.overlay radius]];
[self.mapView addOverlay:circle];
[self.mapView removeOverlay:self.overlay];
self.overlay = circle;
}
}
Note, the map's scrollEnabled has to be turned off for this gesture to be recognized.

Draw Rectangle on the MapView

My application gets data in the following coverage area. I would like to use these boundary values to draw rectangle on the map. Do you have any idea? Thanks in advance
Left Upper Boundary: 30.439217,-95.899668;
Right Upper Boundary: 30.443953,-94.685679;
Left Buttom boundary: 28.930662,-95.908595;
Right Buttom Boundary: 28.930061,-94.690486;
if you wanna draw something basic with lines u can use this MKPolyline
Try the code below, Make sure your delegate is connected with your mapview object
- (void) drawRect
{
CLLocation *coordinates1 = [[CLLocation alloc] initWithLatitude:30.439217 longitude:-95.899668];
CLLocation *coordinates2 = [[CLLocation alloc] initWithLatitude:30.443953 longitude:-94.685679];
CLLocation *coordinates3 = [[CLLocation alloc] initWithLatitude:28.930061 longitude:-94.690486];
CLLocation *coordinates4 = [[CLLocation alloc] initWithLatitude:28.930662 longitude:-95.908595];
NSMutableArray *locationCoordinates = [[NSMutableArray alloc] initWithObjects:coordinates1,coordinates2,coordinates3,coordinates4,coordinates1, nil];
int numberOfCoordinates = [locationCoordinates count];
CLLocationCoordinate2D coordinates[numberOfCoordinates];
for (NSInteger i = 0; i < [locationCoordinates count]; i++) {
CLLocation *location = [locationCoordinates objectAtIndex:i];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[i] = coordinate;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates];
[self.myMapView addOverlay:polyLine];
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor redColor];
polylineView.lineWidth = 1.0;
return polylineView;
}
UPDATE: Here's the swift version of the drawRect function
func drawRect() {
let coordinates1 = CLLocation(latitude: 30.439217, longitude: -95.899668)
let coordinates2 = CLLocation(latitude: 30.443953, longitude: -94.685679)
let coordinates3 = CLLocation(latitude: 28.930061, longitude: -94.690486)
let coordinates4 = CLLocation(latitude: 28.930662, longitude: -95.908595)
let locationCoordinates = [coordinates1,coordinates2,coordinates3,coordinates4,coordinates1]
let coordinates = locationCoordinates.map { $0.coordinate }
let polyLine = MKPolyline(coordinates: coordinates, count: coordinates.count)
mapView.addOver(polyLine)
}
replace the
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay (deprecated)
with
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer
Since you've asked a general question I can only give you a general hint at the answer.
MKMapView has a method convertCoordinate:toPointToView: which turns a coordinate to a point in the view. You can use this to draw on an overlay.
First:
#import <QuartzCore/QuartzCore.h>
Then do this where you want:
CLLocationCoordinate2D koor = CLLocationCoordinate2DMake(30.439217,-95.899668);
CLLocationCoordinate2D koor2 = CLLocationCoordinate2DMake(30.443953,-94.685679);
CLLocationCoordinate2D koor3 = CLLocationCoordinate2DMake(28.930662,-95.908595);
CGPoint point1 = [mapView convertCoordinate:koor toPointToView:mapView];
CGPoint point2 = [mapView convertCoordinate:koor2 toPointToView:mapView];
CGPoint point3 = [mapView convertCoordinate:koor3 toPointToView:mapView];
UIView *someView = [[UIView alloc]initWithFrame:CGRectMake(point1.x, point1.y, point2.x-point1.x, point3.y-point1.y)];
[self viewBicimle:someView];
[someView setBackgroundColor:[UIColor clearColor]];
[someView.layer setBorderColor:[[[UIColor blackColor] colorWithAlphaComponent:1.0] CGColor]];
[someView.layer setBorderWidth:1.0];
[mapView addSubview:someView];
[someView release];
But this will only work for an immovable some MapView. When you move the map it will slide...

Circle Overlay is not showing on map

I am trying to add a circle overlay to a map, but it is not appearing:
- (void) displayOverlayOnMap:(double) lat andlng: (double) lng
{
CLLocationCoordinate2D bostonCoord = CLLocationCoordinate2DMake(lat,lng);
//add MKCircle overlay...
MKCircle *circle = [MKCircle circleWithCenterCoordinate:bostonCoord radius:1000];
[self.mapView addOverlay:circle];
}
Any body have a clue why it's not showing?
here is an example.. you can also find one using polygons on apple's sites: https://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/AnnotatingMaps/AnnotatingMaps.html#//apple_ref/doc/uid/TP40009497-CH6-SW15
or you can use this example
Create overlay from user interaction on MKMapView?
- (void)handleLongPress:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateBegan)
return;
CGPoint touchPoint = [gestureRecognizer locationInView:mapView];
CLLocationCoordinate2D touchMapCoordinate = [mapView convertPoint:touchPoint toCoordinateFromView:mapView];
//add pin where user touched down...
MKPointAnnotation *pa = [[MKPointAnnotation alloc] init];
pa.coordinate = touchMapCoordinate;
pa.title = #"Hello";
[mapView addAnnotation:pa];
[pa release];
//add circle with 5km radius where user touched down...
MKCircle *circle = [MKCircle circleWithCenterCoordinate:touchMapCoordinate radius:5000];
[mapView addOverlay:circle];
}
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay
{
MKCircleView* circleView = [[[MKCircleView alloc] initWithOverlay:overlay] autorelease];
circleView.fillColor = [UIColor redColor];
return circleView;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString *AnnotationIdentifier = #"Annotation";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView)
{
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.animatesDrop = YES;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
Use the code
CLLocationDistance radiusInMeters = 1000;
MKCircle *circle = [MKCircle circleWithCenterCoordinate:bostonCoord radius:radiusInMeters];
Instead of
MKCircle *circle = [MKCircle circleWithCenterCoordinate:bostonCoord radius:1000];
It worked for me.

Resources