How can i customize the MKMapview Annotation With Next and Previous Functionality? - objective-c

HI I have requirement to Implement Next and Previous functionality in the MKMapAnnotationView as shown in the Image.I have got reference from Here for making custom annotation but how can i change the next or previous annotation by clicking Next and Previous button.Please provide some Hint or idea regarding this.I am stack at this point.

For that you can use the rightCalloutAccessoryView and leftCalloutAccessoryView.
Here an example how to use the rightCalloutAccessoryView.
-(MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation: (id<MKAnnotation>)annotation {
if ([annotation isKindOfClass: [MKUserLocation class]]) {
return nil;
}
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
[pinView setCanShowCallout:YES];
if([annotation isKindOfClass:[ASPinAnnotation class]])
{
[pinView setPinColor:MKPinAnnotationColorRed];
}
else if([annotation isKindOfClass:[ASAddAutomatPin class]])
{
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:[annotation title] forState:UIControlStateNormal];
[pinView setRightCalloutAccessoryView:rightButton];
[pinView setPinColor:MKPinAnnotationColorPurple];
}
And to get notified when a calloutAccessoryView is tapped you have to use this function in your delegate:
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
if([(UIButton*)control buttonType] == UIButtonTypeDetailDisclosure)
{
ASAddViewController *addController = [[ASAddViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addController];
[addController setDelegate:self];
[self.controller presentViewController:navController animated:YES completion:nil];
}
}

Related

passing variable from MKAnnotationView to segue

I have an MKMapView, that I drop a number of pins on from an array. Each map pin has an MKAnnotationView that links to a segue and another controller.
All of this is working perfectly now, but I can't see how to pass a variable through the MKAnnotationView to the segue.
I can work with either passing a string or an integer, as I could pass a username as a string, or pass the id of the array and use that in the second view controller after the segue.
My working code for looping through my array, dropping the pins, adding the annotations, and then calling the segue is as below.
This all works fine, populates the map, drops the bins, and the annotations work and link to the new segue. This is all perfect!
I just need to be able to pass a variable through from the map pin array to the second view controller segue.
- (void)loadMapPins {
for (int i=0; i<maparray.count; i++){
Location *item = _feedItems1[i];
CLLocationCoordinate2D myCoordinate = {[item.latitude doubleValue], [item.longitude doubleValue]};
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = myCoordinate;
point.title = item.firstname;
point.subtitle = [NSString stringWithFormat: #"%#", item.username];
[self.mapView addAnnotation:point];
}
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation {
if (annotation == self.mapView.userLocation) return nil;
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView* customPin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
customPin.pinColor = MKPinAnnotationColorRed;
customPin.animatesDrop = YES;
customPin.canShowCallout = YES;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
customPin.rightCalloutAccessoryView = rightButton;
return customPin;
}
- (IBAction)showDetails:(id)sender {
[self performSegueWithIdentifier:#"showProfileFromMap" sender:self];
}
You should use this MKMapViewDelegate method
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
CustomAnnotationClass *annotation = view.annotation;
selectedAnnotationVariable = annotation.yourProperty;
[self performSegueWithIdentifier:#"performSegue" sender:self];
}

Specify which calloutAccessoryControlTapped was called

I am working on an mapkit app which drops pins on the map on certain locations (code at the end)
I have also added code for the callout. However, depending on which pin was tapped I was attemping to load a different views and I have no found any way to do oddly.
I placed a breakpoint and while stepping thru I noticed that there was a line which read.
"annotation.title=#"myhome"; so i was wondering if there way someway i could say what to call depending on which annotation was tapped.
Thanks
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation {
if([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString *identifier = #"myAnnotation";
MKPinAnnotationView * annotationView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!annotationView)
{
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.pinColor = MKPinAnnotationColorRed;
annotationView.animatesDrop = YES;
annotationView.canShowCallout = YES;
}else {
annotationView.annotation = annotation;
}
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return annotationView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
NSLog(#"Callout Tapped");
}
--Updated Code
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation {
if([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// NSLog(annotation);
static NSString *identifier = #"myAnnotation";
MKPinAnnotationView * annotationView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!annotationView)
{
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.pinColor = MKPinAnnotationColorRed;
annotationView.animatesDrop = YES;
annotationView.canShowCallout = YES;
}else {
annotationView.annotation = annotation;
}
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return annotationView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
id <MKAnnotation> annotation = [view annotation];
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
// MKUserLocation *ann = (MKUserLocation *)view.annotation;
// NSLog(#"ann.title = %#", ann.title);
NSLog(#"HJ");
}
}
You could set tags say 1 for left and 2 for right accessory view. And in your calloutAccessoryControlTapped method, do like:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
if ([control tag] == 1) {
NSLog(#"tapped left accessory");
}
else if ([control tag] == 2) {
NSLog(#"tapped right accessory");
}
}

Not displaying DetailDisclosureButton inside annotated view

We are trying to implement MKMapView in iOS application.I got the mapView with the given locations and pins.When I tap on these pins I am getting the title and subtitle also.Now I want to include a detail Disclosure button in this view in which the title and subtitle are displayed.For that I used the below given code[MKPinannotation detail disclosure button - present new view is going inside the first method but it is not showing the detailDisclosureButton.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"pinView"];
if (!pinView) {
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"pinView"] autorelease];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView = rightButton;
} else {
pinView.annotation = annotation;
}
return pinView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped
{
}
Now what can I do?Anyone please take a look and help me...
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation {
pinView = nil;
if(annotation != map.userLocation)
{
NSString *defaultPinID =#"com.invasivecode.pin1";
pinView = (MKPinAnnotationView *)[map dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil ) pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
UIButton *btnGo = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[btnGo addTarget:self action:#selector(goToLocation:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView=btnGo;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
pinView.draggable=NO;
}
else {
[map.userLocation setTitle:#"I am here"];
}
return pinView;
}
Declare this in .h file
MKPinAnnotationView *pinView
please try setting the frame for rightButton i.e
rightButton.frame = CGRectMAke (x,y,width,height);

Add annotation pin on touch using MapKit and UIGestureRecognizer

I have some problems with adding annotations when the user touch the map.
I'm using UIGestureRecognizer to detect the user's touch.
When a long press is detected, I'm calling this function :
- (void)handleLongPressGesture:(UIGestureRecognizer*)gestureRecognizer{
if (gestureRecognizer.state == UIGestureRecognizerStateEnded) return;
NSLog(#"long press");
CGPoint touchPoint = [gestureRecognizer locationInView:mapView];
CLLocationCoordinate2D touchMapCoordinate =
[mapView convertPoint:touchPoint toCoordinateFromView:mapView];
RdvAnnotation *rdvAnnotation = [[RdvAnnotation alloc] init];
[rdvAnnotation initWithCoordinate:touchMapCoordinate];
[mapView removeAnnotations:mapView.annotations];
[mapView addAnnotation:rdvAnnotation];
[rdvAnnotation release]; }
I cans see the NSLog in the console and the rdvAnnotation is initialized with the good coordinate.
I don't understand why I can't see my annotation on the map.
Here's my - (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation method:
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
if ([annotation isKindOfClass:[RdvAnnotation class]])
{
static NSString* RdvAnnotationIdentifier = #"rdvAnnotationIdentifier";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)
[mapView dequeueReusableAnnotationViewWithIdentifier:RdvAnnotationIdentifier];
if (!pinView)
{
MKPinAnnotationView* customPinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:RdvAnnotationIdentifier] autorelease];
customPinView.pinColor = MKPinAnnotationColorPurple;
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
return nil;}
My viewDidLoad method:
- (void)viewDidLoad {
[super viewDidLoad];
mapView = [[MKMapView alloc] initWithFrame:self.view.frame];
[mapView setShowsUserLocation:TRUE];
[mapView setMapType:MKMapTypeStandard];
[mapView setDelegate:self];
CLLocationManager *locationManager=[[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[locationManager startUpdatingLocation];
self.navigationItem.title = #"Rendez-vous" ;
}
I just noticed something that seems weird :
RdvAnnotation *rdvAnnotation = [[RdvAnnotation alloc] init];
[rdvAnnotation initWithCoordinate:touchMapCoordinate];
You're calling init twice on the annotation object. You should just do it this way :
RdvAnnotation *rdvAnnotation = [[RdvAnnotation alloc] initWithCoordinate:touchMapCoordinate]];
EDIT :
If you have code in your init method that you don't want to lose, keep the init and change the value of the coordinate property :
RdvAnnotation *rdvAnnotation = [[RdvAnnotation alloc] init];
rdvAnnotation.coordinate = touchMapCoordinate;
In viewDidLoad you are creating a new map view object.
First, this new map view object is not being added as a subview to self.view so it exists in memory but is invisible.
Second, you probably already have a map view object placed in the view in Interface Builder so you don't need to create a new one.
So what is probably happening is that when you add the annotation, it is being added to the map view object in memory but not the one that is visible (the one that was created in IB).
Instead of creating a new map view in viewDidLoad, connect the mapView IBOutlet to the map view in Interface Builder.

Showing the Pin Information by Default

I am working with MKPinAnnotationView annotations pins over a MKMapView. Into the view that I am developing, there is a map centered on a pin. When I call the view the pin drops down and if I make a click over it, it shows the annotation information (canShowCallout = YES). How I can get this callout just when I open the view? Without making a click over the annotation pin.
Thanks for reading.
Edited:
I am using this code.
- (void)viewDidLoad {
[super viewDidLoad];
AddressAnnotation *annotation = [[[AddressAnnotation alloc] initWithCoordinate:self.currentAnnotationCoordinate] autorelease];
[self.mapView addAnnotation:annotation];
[self zoomCoordinate:self.currentAnnotationCoordinate];
}
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation {
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
else { // Handles the other annotations.
// Try to dequeue an existing pin view first.
static NSString *AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView) {
// If an existing pin view was not available, creates one.
MKPinAnnotationView *customPinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
// Adds a detail disclosure button.
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;
} else
pinView.annotation = annotation;
}
return nil;
}
- (void)mapViewDidFinishLoadingMap:(MKMapView *)theMapView {
AddressAnnotation *annotation = [[[AddressAnnotation alloc] initWithCoordinate:self.currentAnnotationCoordinate] autorelease];
for (id<MKAnnotation> currentAnnotation in mapView.annotations) {
if ([currentAnnotation isEqual:annotation]) {
[mapView selectAnnotation:currentAnnotation animated:FALSE];
}
}
}
Edited:
Calling didAddAnnotationViews: instead of mapViewDidFinishLoadingMap: (as aBitObvious has commented), it works fine.
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
id<MKAnnotation> myAnnotation = [self.mapView.annotations objectAtIndex:0];
[self.mapView selectAnnotation:myAnnotation animated:YES];
}
Possible duplicate: How to trigger MKAnnotationView's callout view without touching the pin?
You want to call [mapView selectAnnotation:].