I have a button on Map which directs to "MyLocation" its hardcore lat n lng. i want to change the pin color. Tried some but not successful. Heres the code.
- (IBAction)btnMylLocation:(UIButton *)sender {
CLLocationCoordinate2D coord = {.latitude = 18.520430, .longitude = 73.856744};
MKCoordinateSpan span = {.latitudeDelta = 0.2, .longitudeDelta = 0.2};
MKCoordinateRegion region = {coord, span};
[self.mapView setRegion:region];
CLLocationCoordinate2D annotationCoord;
annotationCoord.latitude = 18.520430;
annotationCoord.longitude = 73.856744;
self.lblLongitude.text = [NSString stringWithFormat:#"%f ", annotationCoord.latitude];
self.lblLatitude.text = [NSString stringWithFormat:#" %f", annotationCoord.longitude];
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
annotationPoint.coordinate = annotationCoord;
annotationPoint.title = #"Mindbowser";
annotationPoint.subtitle = #"Pune Headquater's";
[_mapView addAnnotation:annotationPoint];
}
You need to implement the map's delegate method and set the delegate.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// Handle any custom annotations.
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if (!pinView)
{
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.pinColor = MKPinAnnotationColorGreen;
}
else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
In your viewDidLoad() , write the following code
_mapView.delegate = self;
This may help you.
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
MKPinAnnotationView *annotationView = nil;
if(![annotation isKindOfClass:[MKUserLocation class]]){
annotationView=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:#"pin"];
annotationView.pinColor = MKPinAnnotationColorGreen;
}
return annotationView;
}
Implement the delegate method below and return MKAnnotationView by assigning the pinTintColor it is available from iOS 9.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString *annotaionIdentifier=#"annotationIdentifier";
MKPinAnnotationView *aView=(MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:annotaionIdentifier ];
if (aView==nil) {
aView=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:annotaionIdentifier];
aView.pinTintColor = [UIColor yellowColor];//from iOS 9, you can pass in any color you want.
//aView.pinColor = MKPinAnnotationColorPurple //if iOS is less than 9.0
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
aView.animatesDrop=TRUE;
aView.canShowCallout = YES;
aView.calloutOffset = CGPointMake(-5, 5);
}
return aView;
}
To change color while adding annotation, check below method.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation
(id<MKAnnotation>)annotation {
static NSString *identifier = #"PinAnnotationIdentifier";
MKPinAnnotationView *pinAnnotation = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if(!pinAnnotation) {
pinAnnotation = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
}
pinAnnotation.pinColor = MKPinAnnotationColorGreen; //Color
return pinAnnotation;
}
Use below method for changing color on select and deselect.
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKPinAnnotationView *)view {
view.pinColor = MKPinAnnotationColorRed;
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKPinAnnotationView *)view {
view.pinColor = MKPinAnnotationColorGreen;
}
Related
I have 2 MKPointAnnotation and i want to display them on map with two different pins(MKAnnotationView having image).
// MKPointAnnotation - 1
CLLocationCoordinate2D cordinate;
cordinate.latitude = [_latitudeString doubleValue];
cordinate.longitude = [_longitudeString doubleValue];
MKPointAnnotation *point1 = [[MKPointAnnotation alloc] init];
point1.coordinate = CLLocationCoordinate2DMake(cordinate.latitude, cordinate.longitude);
[self.mapView addAnnotation:point1];
P.S - When i get second MKPointAnnotation i needed self zoom on that area.
// MKPointAnnotation - 2
CLLocationCoordinate2D cordinate;
cordinate.latitude = [_latStr doubleValue];
cordinate.longitude = [_longStr doubleValue];
MKPointAnnotation *point2 = [[MKPointAnnotation alloc] init];
point2.coordinate = CLLocationCoordinate2DMake(cordinate.latitude, cordinate.longitude);
[self.mapView addAnnotation:point2];
//This is my code for MKAnnotationView
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if ([annotation isKindOfClass:[MKPointAnnotation class]]){
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if(!pinView){
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"annotation"];
pinView.calloutOffset = CGPointMake(0, 0);
}
else{
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
What i need to change in the viewForAnnotation method?
For example, you can create subclass of MKPointAnnotation.
#interface SecondAnnotation: MKPointAnnotation
#end
#implementation SecondAnnotation
#end
Add SecondAnnotation to the mapView.
// MKPointAnnotation - 2
...
SecondAnnotation *point2 = [[SecondAnnotation alloc] init];
point2.coordinate = CLLocationCoordinate2DMake(cordinate.latitude,
cordinate.longitude);
[self.mapView addAnnotation:point2];
You can use different MKAnnotationView with the following code.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if ([annotation isKindOfClass:[MKPointAnnotation class]]){
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if(!pinView){
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"Annotation"];
pinView.calloutOffset = CGPointMake(0, 0);
}
else{
pinView.annotation = annotation;
}
return pinView;
} else if ([annotation isKindOfClass:[SecondAnnotation class]]){
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if(!pinView){
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"Second"];
pinView.calloutOffset = CGPointMake(0, 0);
}
else{
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
Writing the viewForAnnotation as below solved my problem -
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if ([annotation isKindOfClass:[MKPointAnnotation class]]){
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if(!pinView){
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"annotation"];
pinView.calloutOffset = CGPointMake(0, 0);
}
else{
pinView.annotation = annotation;
if ([annotation isKindOfClass:[SecondAnnotation class]]) {
pinView.image = [UIImage imageNamed:#"range"];
}
else{
pinView.image = [UIImage imageNamed:#"annotation"];
}
}
return pinView;
}
return nil;
}
I have a an array of latitude and longitude and using for loop am displaying the MKPointAnnotation on the map. I want to show a view as a popup with data when the specific MKPointAnnotation is tapped.
Here is my code -
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 10000, 10000);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
[_locationManager stopUpdatingLocation];
NSArray *set = [[NSArray alloc] init];
for (int i = 0; i < _json.count; i++) {
_name = [_json[i] valueForKey:#"name"];
_class = [_json[i] valueForKey:#"class"];
set = [_json[i] valueForKey:#"set"];
if (setFreeHour.count != 0) {
for (int j=0;j<set.count;j++) {
NSDictionary *dict = [[NSDictionary alloc] init];
dict = set[j];
_lat = dict[#"latitude"];
_longi = dict[#"longitude"];
CLLocationCoordinate2D coordinate;
coordinate.latitude = [_lat doubleValue];
coordinate.longitude = [_longi doubleValue];
// Add an annotation
MKPointAnnotation *point1 = [[MKPointAnnotation alloc] init];
point1.coordinate = CLLocationCoordinate2DMake(coordinate.latitude, coordinate.longitude);
point1.title = _name;
point1.subtitle = _class;
[self.mapView addAnnotation:point1];
}
}
}
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// Handle any custom annotations.
if ([annotation isKindOfClass:[MKPointAnnotation class]]) {
// Try to dequeue an existing pin view first.
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if (!pinView) {
// If an existing pin view was not available, create one.
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"annotation"];
pinView.calloutOffset = CGPointMake(0, 0);
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showDetails)];
[pinView addGestureRecognizer:tap];
} else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
- (void)showDetails{
self.popup.hidden = NO;
}
//PS: popup is a view that contains labels. I want to pass data from MKPointAnnotation to the view
Why don't you use mapView(_:didSelect:) method instead of UITapGestureRecognizer?
(void)mapView:(MKMapView *)mapview didSelectAnnotationView:(MKAnnotationView *)view {
// 1. get data from view(MKAnnotationView)
// 2. pass data to another view
}
https://developer.apple.com/documentation/mapkit/mkmapviewdelegate/1452393-mapview
I am trying to create custom annotation as each annotation save some data which i need to show on tap of pin. But i need to show default ios pin image. Everything is working fine but pin will only show when i set any image. without setting image it is not showing default ios pin. My code is
CustomAnnotation.h file
#interface CustomAnnotation : NSObject<MKAnnotation>
#property(nonatomic,strong)NSString *title;
#property(nonatomic,strong)NSString *subTitle;
#property(nonatomic)CLLocationCoordinate2D coordinate;
#property(nonatomic,strong) UserDevice *userData;
-(instancetype)initWithUserData:(UserDevice *)userData;
on mapViewC.h
-(void)addMarkersOnMap{
for (UserDevice* userDevice in markersArray) {
CustomAnnotation *point = [[CustomAnnotation alloc]initWithUserData:userDevice];
point.coordinate = CLLocationCoordinate2DMake(userDevice.latitude, userDevice.longitude);
point.userData = userDevice;
point.title = #"dszf";
[mapview addAnnotation:point];
MKMapRect mapRect = [self getZoomingRectOnMap:mapview toFitAllOverlays:YES andAnnotations:YES includeUserLocation:NO];
[mapview setVisibleMapRect:mapRect edgePadding:UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0) animated:YES];
}
}
#pragma mark - MKMapView Delegate methods
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
if ([annotation isKindOfClass:[CustomAnnotation class]]) {
CustomAnnotation *customAnnotation = annotation;
MKAnnotationView *customAnnotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"annotationViewID"];
if (customAnnotationView == nil){
customAnnotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"annotationViewID"];
}
// customAnnotationView.image = [UIImage imageNamed:#"pin-1"];
customAnnotationView.canShowCallout = true;
customAnnotationView.annotation = customAnnotation;
return customAnnotationView;
}
return nil;
}
Instead of CustomAnnotationView use MKPinAnnotationView in your viewForAnnotation MKMapViewDelegate method
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
if ([annotation isKindOfClass:[CustomAnnotation class]]) {
CustomAnnotation *customAnnotation = annotation;
MKPinAnnotationView *customAnnotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"annotationViewID"];
if (customAnnotationView == nil){
customAnnotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"annotationViewID"];
}
// customAnnotationView.image = [UIImage imageNamed:#"pin-1"];
customAnnotationView.canShowCallout = true;
customAnnotationView.annotation = customAnnotation;
return customAnnotationView;
}
return nil;
}
Hope this helps
CustomAnnotation *customAnnotation = annotation;
NSString *annotationIdentifier = #"PinViewAnnotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier: annotationIdentifier];
if (pinView ==nil) {
pinView = [[MKPinAnnotationView alloc]initWithAnnotation: customAnnotation reuseIdentifier: annotationIdentifier];
}
pinView.pinColor = MKPinAnnotationColorGreen; // change color
pinView.canShowCallout = YES;
pinView.enabled = YES;
mapView selectAnnotation:pinView animated:YES];
trying to pass my annotation's data (name, address, phone #, url, description, etc) to a DetailViewController with a table. stuck----please read the code. the data isnt passed with calloutAccessoryTapped. Help?
- (IBAction)gasButton:(id)sender {
[self.mapView removeAnnotations:self.mapView.annotations];
self.localSearchRequest = [[MKLocalSearchRequest alloc] init];
self.localSearchRequest.region = self.mapView.region;
self.localSearchRequest.naturalLanguageQuery = #"gas station";
self.localSearch = [[MKLocalSearch alloc] initWithRequest:self.localSearchRequest];
[self.localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
if(error){
NSLog(#"localSearch startWithCompletionHandlerFailed! Error: %#", error);
return;
} else {
for(mapItem in response.mapItems){
MKPointAnnotation *zip = [[MKPointAnnotation alloc] init ];
zip.coordinate = mapItem.placemark.location.coordinate;
zip.title = mapItem.name;
self.mapView.delegate = self;
[self.mapView addAnnotation: zip];
[self.mapView selectAnnotation:zip animated:YES];
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow];
NSLog(#"%# - 1", mapItem.name);
CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:zip.coordinate.latitude longitude:zip.coordinate.longitude];
CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:self.mapView.userLocation.coordinate.latitude longitude:self.mapView.userLocation.coordinate.longitude];
CLLocationDistance distance = [loc1 distanceFromLocation:loc2];
NSString *dist = [[NSString alloc] initWithFormat:#"%.2f miles", distance * 0.000621371192];
zip.subtitle = dist;
}
}
}];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKPinAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"MYVC"];
if ([annotation isKindOfClass:[MKUserLocation class]])
{
return nil;
}
else if ([annotation isKindOfClass: [MKPointAnnotation class] ])
{
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.enabled = YES;
annotationView.animatesDrop = YES;
annotationView.pinColor = MKPinAnnotationColorGreen;
annotationView.canShowCallout = YES;
NSLog(#"%# - 2", mapItem.name);
return annotationView;
}
return nil;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"%# - tapped", mapItem.name);
//STUCK HERE - mapItem.name is (null)
}
mapItem exists in the for loop of your gasButton function, no where else as far as I can see. You've created an annotation (zip) and added it to your map. In viewForAnnotation you are given that annotation as a parameter and asked to make an annotationView from it. In calloutAccessoryControlTapped you are given an annotationView and told it has been tapped. You need to follow the chain back to your data. From the annotationView get the annotation and from the annotation get your name.
MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"%# - tapped", view.annotation.title);
}
How do I show images instead of pins in the map. So far I can only add pins on tap. A sample code of the .m would extremely help since i'm still new to iOS programming.
#pragma mark -
#pragma mark MKMapView delegate
- (MKAnnotationView *)mapView:(MKMapView *)mapview viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if(annotationView)
return annotationView;
else
{
MKAnnotationView *annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:AnnotationIdentifier] autorelease];
annotationView.canShowCallout = YES;
annotationView.image = [UIImage imageNamed:#"someImage.png"];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(writeSomething:) forControlEvents:UIControlEventTouchUpInside];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
annotationView.rightCalloutAccessoryView = rightButton;
annotationView.canShowCallout = YES;
annotationView.draggable = YES;
return annotationView;
}
return nil;
}
EDIT:
I could explain to you all about the MKAnnotationView, but I think you will find the documentation provided by Apple to be a far better explanation than from any other source. Check the overview section in the link.
https://developer.apple.com/documentation/mapkit/mkannotationview
Go to organizer of Xcode and then go to documentation and search weatherMap it shows example for map with including images at annotation.
#pragma mark -
#pragma mark MKMapView delegate
-(void)addAllPinsOnMapView
{
MKCoordinateRegion region = mapViewOffer.region;
region.center = CLLocationCoordinate2DMake(12.9752297537231, 80.2313079833984);
region.span.longitudeDelta= 0.1f;
region.span.latitudeDelta= 0.1f;
[mapViewOffer setRegion:region animated:YES];
mapViewOffer.delegate=self;
arrMapPin=[[NSMutableArray alloc] init];
NSArray *name=[[NSArray alloc]initWithObjects:
#"Title1",
#"Title2",
#"Title3", nil];
NSMutableArray *arrCoordinateStr = [[NSMutableArray alloc] initWithCapacity:name.count];
[arrCoordinateStr addObject:#"12.970760345459,80.2190093994141"];
[arrCoordinateStr addObject:#"12.9752297537231,80.2313079833984"];
[arrCoordinateStr addObject:#"12.9788103103638,80.2412414550781"];
for(int i = 0; i < name.count; i++)
{
NSArray *components = [[arrCoordinateStr objectAtIndex:i] componentsSeparatedByString:#","];
double latitude = [components[0] doubleValue];
double longitude = [components[1] doubleValue];
MKPointAnnotation *mapPin = [[MKPointAnnotation alloc] init];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
mapPin.title = [name objectAtIndex:i];
mapPin.coordinate = coordinate;
[mapViewOffer addAnnotation:mapPin];
}
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:
(MKAnnotationView *)view
{
NSLog(#"%#",view.annotation.title);
NSLog(#"%f",view.annotation.coordinate.latitude);
NSLog(#"%f",view.annotation.coordinate.longitude);
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(calloutTapped:)];
[view addGestureRecognizer:tapGesture];
}
-(void)calloutTapped:(UITapGestureRecognizer *) sender
{
NSLog(#"Callout was tapped");
MKAnnotationView *view = (MKAnnotationView*)sender.view;
id <MKAnnotation> annotation = [view annotation];
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
//[self performSegueWithIdentifier:#"annotationDetailSegue" sender:annotation];
OfferDetailsViewController *objOfferDetailsViewController = [[OfferDetailsViewController alloc]init];
[self.navigationController pushViewController:objOfferDetailsViewController animated:YES];
}
}
- (MKAnnotationView *)mapView:(MKMapView *)theMapView
viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
static NSString *defaultPinID = #"annotationViewID";
pinView = (MKAnnotationView *)[mapViewOffer dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil ){
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID];
}
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"placeholder"];
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[infoButton addTarget:self action:#selector(infoButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = infoButton;
return pinView;
}