iOS - Mkmapview Place Annotation by Using Address Instead of Lat/Long

iOS - MKMapView place annotation by using address instead of lat / long

Based on psoft's excellent information, I was able to achieve what I was looking for with this code.

NSString *location = @"some address, state, and zip";
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:location
completionHandler:^(NSArray* placemarks, NSError* error){
if (placemarks && placemarks.count > 0) {
CLPlacemark *topResult = [placemarks objectAtIndex:0];
MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:topResult];

MKCoordinateRegion region = self.mapView.region;
region.center = placemark.region.center;
region.span.longitudeDelta /= 8.0;
region.span.latitudeDelta /= 8.0;

[self.mapView setRegion:region animated:YES];
[self.mapView addAnnotation:placemark];
}
}
];

Show address in annotation when pin is dropped on map

First, in the addPinToMap: method, addressLocation is called with currentLocation but currentLocation is never set. It's declared a few lines up but not set to any value.

So change:

CLLocation *currentLocation;

to:

CLLocation *currentLocation = [[CLLocation alloc] 
initWithLatitude:touchMapCoordinate.latitude
longitude:touchMapCoordinate.longitude];



Second, even with this fix, it still won't work. The annotation's title will not get set because the reverseGeocodeLocation method's completion handler block will finish after the annotation has already been added (the block is asynchronous -- the code in addPinToMap: will not wait for it to finish).

You'll need to change the code around a bit and add the annotation inside the completion block when you actually have the geocoder result (whether success or failure).

Move the reverseGeocodeLocation call to the addPinToMap: method:

CLLocation *currentLocation = [[CLLocation alloc] 
initWithLatitude:touchMapCoordinate.latitude
longitude:touchMapCoordinate.longitude];

[self.geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemark, NSError *error) {

//initialize the title to "unknown" in case geocode has failed...
NSString *annTitle = @"Address unknown";

//set the title if we got any placemarks...
if (placemark.count > 0)
{
CLPlacemark *topResult = [placemark objectAtIndex:0];
annTitle = [NSString stringWithFormat:@"%@ %@ %@ %@", topResult.country, topResult.locality, topResult.subLocality, topResult.thoroughfare];
}

//now create the annotation...
MapAnnotation *toAdd = [[MapAnnotation alloc]init];

toAdd.coordinate = touchMapCoordinate;
toAdd.title = annTitle;
toAdd.subtitle = @"Subtitle";

[self.map addAnnotation:toAdd];
}];

Mapkit, how to change annotation coordinates to nearest address?

I would just use a reverse geocode here returning an MKPlacemark. The documentation suggests that normally just one placemark will be returned by the completion handler, on the main thread, so you can use the result straightaway to update the UI. MKPlacemark conforms to the annotation protocol so you can put it directly on the map:

func resolveAddress(for averageCoordinate: CLLocationCoordinate2D, completion: @escaping (MKPlacemark?) -> () ) {

let geocoder = CLGeocoder()
let averageLocation = CLLocation(latitude: averageCoordinate.latitude, longitude: averageCoordinate.longitude)
geocoder.reverseGeocodeLocation(averageLocation) { (placemarks, error) in
guard error == nil,
let placemark = placemarks?.first
else {
completion(nil)
return
}
completion(MKPlacemark(placemark: placemark))
}
}

@IBAction func middleFinderButton(_ sender: Any) {

// your code to find center annotation

resolveAddress(for: centerPoint.coordinate) { placemark in
if let placemark = placemark {
self.mapView.addAnnotation(placemark)
} else {
self.mapView.addAnnotation(centerCoordinate)
}
}

Setting the title and subtitle on a Map Annotation view

Use MKPointAnnotation instead.

Sample Code :

CLPlacemark *topresult = [placemarks objectAtIndex:0];
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
annotation.coordinate = topresult.location.coordinate;
annotation.title = self.business.businessName;
annotation.subtitle = self.business.phoneNumber;
[self.mapView addAnnotation:annotation];

How can i get any information like lat,long when i touch on MKMapView in iPhone/iPad?

With iOS 3.2 or greater, it's probably better and simpler to use a UIGestureRecognizer with the map view instead of trying to subclass it and intercepting touches manually.

First, add the gesture recognizer to the map view:

UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] 
initWithTarget:self action:@selector(tapGestureHandler:)];
tgr.delegate = self; //also add <UIGestureRecognizerDelegate> to @interface
[mapView addGestureRecognizer:tgr];
[tgr release];

Next, implement shouldRecognizeSimultaneouslyWithGestureRecognizer and return YES so your tap gesture recognizer can work at the same time as the map's (otherwise taps on pins won't get handled automatically by the map):

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldRecognizeSimultaneouslyWithGestureRecognizer
:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}

Finally, implement the gesture handler:

- (void)tapGestureHandler:(UITapGestureRecognizer *)tgr
{
CGPoint touchPoint = [tgr locationInView:mapView];

CLLocationCoordinate2D touchMapCoordinate
= [mapView convertPoint:touchPoint toCoordinateFromView:mapView];

NSLog(@"tapGestureHandler: touchMapCoordinate = %f,%f",
touchMapCoordinate.latitude, touchMapCoordinate.longitude);
}

MKMapview place pin at location (long/lat)

Find the below very simple solution to drop the pin at given location define by CLLocationCoordinate2D

Drop Pin on MKMapView

Edited:

CLLocationCoordinate2D  ctrpoint;
ctrpoint.latitude = 53.58448;
ctrpoint.longitude =-8.93772;
AddressAnnotation *addAnnotation = [[AddressAnnotation alloc] initWithCoordinate:ctrpoint];
[mapview addAnnotation:addAnnotation];
[addAnnotation release];

Plotting a Specific Location on map view with latitude and longitude

For the "previous one also remains on the screen" problem: don't keep making a new annotation and calling addAnnotation if you don't want to keep adding new annotations. Instead, keep hold of the annotation that you add, and move it later using its coordinate property. Something like this maybe:

class ViewController: UIViewController, MKMapViewDelegate {

@IBOutlet weak var mapView: MKMapView!

var annotationForThing: MKPointAnnotation?
var coordinateOfThing: CLLocationCoordinate2D? {
didSet {
guard let newCoord = coordinateOfThing else {
if let existing = annotationForThing {
mapView.removeAnnotation(existing)
}
return
}
if let existing = annotationForThing {
existing.coordinate = coordinateOfThing
}
else {
let newAnnotation = MKPointAnnotation()
newAnnotation = coordinateOfThing
mapView.addAnnotation(newAnnotation)
annotationForThing = newAnnotation
}
}
}

override func viewDidLoad() {
super.viewDidLoad()

mapView.delegate = self // or connect in storyboard
}


Related Topics



Leave a reply



Submit