I have a cluster of annotation pins in map view. When I clicked on the pin I get the index of that pin. I want that if I click on the pin than all the pins are hide except that on which user clicked and if again I click on that pin all the pins are shown.
Here is the code in which I got the index of the selected pin.
CPointAnnotation *cAnno=(CPointAnnotation*)view.annotation;
NSInteger index=cAnno.index;
if (index<hospitalsArry.count) {
selectedHospital=[hospitalsArry objectAtIndex:index];
if (selectedIndex==index) {
selectedIndex=-1;
return;
}else{
selectedIndex=index;
[[self.mapView viewForAnnotation:cAnno] setHidden:NO];
}
CustomAnnotation.h
#import <MapKit/MapKit.h>
#interface CustomAnnotation : NSObject <MKAnnotation>
#property (nonatomic,readonly)CLLocationCoordinate2D coordinate;
#property (nonatomic, copy)NSString *title;
#property (nonatomic, strong)MKAnnotationView *annotaitonView;
-(id)initWithTitle:(NSString *)newTitle coordinates:(CLLocationCoordinate2D)newCoordinate;
-(MKAnnotationView *)createAnnotationView;
#end
CustomAnnotation.m
#implementation CustomAnnotation
-(id)initWithTitle:(NSString *)newTitle coordinates:(CLLocationCoordinate2D)newCoordinate
{
if (self = [super init]) {
_title = newTitle;
_coordinate = newCoordinate;
}
return self;
}
-(MKAnnotationView *)createAnnotationView
{
MKAnnotationView *annView=[[MKAnnotationView alloc]initWithAnnotation:self reuseIdentifier:#"MyCustomAnnoation"];
annView.enabled=TRUE;
annView.canShowCallout=TRUE;
annView.image=[UIImage imageNamed:#"map-pin-marker-circle-128.png"];
return annView;
}
#end
in MapViewController.m
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MKPointAnnotation class]]) {
return nil;
}
if ([annotation isKindOfClass:[CustomAnnotation class]]) {
CustomAnnotation *myAnn=(CustomAnnotation *)annotation;
MKAnnotationView *annView=[mapView dequeueReusableAnnotationViewWithIdentifier:#"MyCustomAnnoation"];
if (annView == nil) {
annView=[myAnn createAnnotationView];
}
else
{
annView.annotation=myAnn;
}
myAnn.annotaitonView=annView;
return annView;
}
else
return nil;
}
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
[self hideOtherPinsByIgnoringThis:view];
}
-(void)hideOtherPinsByIgnoringThis:(MKAnnotationView *)ann
{
NSArray *arrAllPins=[self.myMapView annotations];
//Find selected Annotation View in all pins on map
NSMutableArray *removeAnn=[[NSMutableArray alloc]init];
for (CustomAnnotation *annotation in arrAllPins)
{
if (annotation.annotaitonView != ann) {
[removeAnn addObject:annotation];
}
}
[self.myMapView removeAnnotations:removeAnn];
}
Related
I have create BubbleView in mapview. In bubble i have put the button but i have not click on button.
How can i implement please help me.
I have tried.......
customCalloutView.h
#import <UIKit/UIKit.h>
#interface customCalloutView : UIView
#property (nonatomic, retain) IBOutlet UIButton *BubbleBtn;
customCalloutView.m
#import "customCalloutView.h"
#implementation customCalloutView
{
}
#end
Delegate method of mapview in anotherclass
- (MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
static NSString *identifier=#"MyAnnotation";
NSLog(#"anotioni s:%#",annotation);
//CLLocationCoordinate2D pinCoordinate = [self.pickupLocationView convertPoint:CGPointMake(self.pickupLocationView.frame.size.width / 2, self.pickupLocationView.frame.size.height) toCoordinateFromView:self.view];
MKAnnotationView *annotationView=(MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!annotationView)
{
annotationView=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.image=[UIImage imageNamed:#"mapPin"];
} else
{
annotationView.annotation=annotation;
}
return annotationView;
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
customCalloutView *callOutView=nil;
callOutView.userInteractionEnabled=YES;
if (callOutView == nil)
{
NSArray *nib=[[NSBundle mainBundle]loadNibNamed:#"customCalloutView" owner:self options:nil];
callOutView=[nib objectAtIndex:0];
}
[callOutView.BubbleBtn addTarget:self action:#selector(BtnDetailclick:) forControlEvents:UIControlEventTouchUpInside];
CGRect callOutViewFrame=callOutView.frame;
callOutViewFrame.origin=CGPointMake(-callOutViewFrame.size.width/2+14 , -callOutViewFrame.size.height);
callOutView.frame=callOutViewFrame;
// [callOutView.BtnDetail setTitle:#"Change" forState:UIControlStateNormal];
[view addSubview:callOutView];
}
-(IBAction)BtnDetailclick:(UIButton *)sender
{
NSLog(#"Hello");
}
I need MKAnnotation with different pin image.
So I created following:
#interface NavigationAnnotation : NSObject <MKAnnotation>
- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate;
...
#interface NavigationAnnotation ()
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *address;
#property (nonatomic, assign) CLLocationCoordinate2D theCoordinate;
#end
#implementation NavigationAnnotation
- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate {
if ((self = [super init])) {
if ([name isKindOfClass:[NSString class]]) {
self.name = name;
} else {
self.name = #"Unknown charge";
}
self.address = address;
self.theCoordinate = coordinate;
}
return self;
}
- (NSString *)title {
return _name;
}
- (NSString *)subtitle {
return _address;
}
- (CLLocationCoordinate2D)coordinate {
return _theCoordinate;
}
And add it like this:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
static NSString *identifier_OrderAnnotation = #"NavigateAnnotation";
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
if ([annotation isKindOfClass:[NavigationAnnotation class]]) {
MKAnnotationView *annotationView = (MKAnnotationView *) [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier_OrderAnnotation];
if (annotationView == nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier_OrderAnnotation];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.draggable = YES;
annotationView.image = [UIImage imageNamed:#"myimage.png"];
} else {
annotationView.annotation = annotation;
}
return annotationView;
}
}
Annotation shows on map fine but it is not draggable from some reason :(
As already mentioned, for an annotation to be draggable, it must implement a setCoordinate: method.
Additionally, since iOS 7, you may also need to implement the mapView:annotationView:didChangeDragState: method (see Draggable Pin does not have a fixed position on map and iOS MapKit dragged annotations (MKAnnotationView) no longer pan with map).
You can either implement the setCoordinate: method explicitly yourself or just declare a writeable coordinate property (named exactly like that) and synthesize it (and the getter and setter methods will be automatically implemented for you).
(Note that if you use the pre-defined MKPointAnnotation class, you don't need to do this because that class already implements a settable coordinate property.)
In your NavigationAnnotation class, to implement the explicit, manual solution to work with the existing theCoordinate property, just add the setCoordinate: method to your class implementation (keep the existing getter method):
-(void)setCoordinate:(CLLocationCoordinate2D)newCoordinate
{
self.theCoordinate = newCoordinate;
}
You may also need to implement the didChangeDragState: method in the class that implements the map view delegate (the same one that has the viewForAnnotation method) otherwise after dragging, the annotation view will hover in-place above the map even while it is panned or zoomed underneath. An example implementation of the method as given by Chris K. in his answer:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState
{
if (newState == MKAnnotationViewDragStateStarting)
{
annotationView.dragState = MKAnnotationViewDragStateDragging;
}
else if (newState == MKAnnotationViewDragStateEnding || newState == MKAnnotationViewDragStateCanceling)
{
annotationView.dragState = MKAnnotationViewDragStateNone;
}
}
Just went through this issue...
After some struggling, reason was different (title, coordinate were ok), so adding possible cause here
In my annotation view, I did override - (void) setSelected:(BOOL)selected
Without calling [super setSelected:selected];
This prevented the dragging from occuring...
In my app I am displaying a tableview which contains result of searched user from database. Now in that tableview there is one button by clicking on that user can see location of all searched users in map.when user first click on button he will be able to see all user's location with green color pin. I am displaying map in half part of view. Now When user select any particular searched user from table I want to change color of that user's pin.And if user select any other user from table previous selected user's pin color should be changed to as it was before.
I have tried this:
- (void)selectAnnotation:(id < MKAnnotation >)annotation animated:(BOOL)animated{
MKPinAnnotationView *chng=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:nil];
chng.pinColor=MKPinAnnotationColorRed;
NSLog(#"========>selected");
}
And I am calling this method when user select particular user from table.
CLLocationCoordinate2D CurrentCoordinateSingleUser;
CurrentCoordinateSingleUser.latitude=[[singleUserPin objectAtIndex:1] doubleValue];
CurrentCoordinateSingleUser.longitude=[[singleUserPin objectAtIndex:2] doubleValue];
MapObjects *map1=[[MapObjects alloc]initwithCoordinate:CurrentCoordinateSingleUser title:[singleUserPin objectAtIndex:0] subtitle:Nil];
[userMap addAnnotation:map1];
for (id<MKAnnotation> currentAnnotation in userMap.annotations) {
if ([currentAnnotation isEqual:annotationToSelect]) {
[userMap selectAnnotation:currentAnnotation animated:FALSE];
}
}
But here selectAnnotation is not working.
UPDATE::
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString *identifier = #"myAnnotation";
MKPinAnnotationView * annotationView = (MKPinAnnotationView*)[userMap dequeueReusableAnnotationViewWithIdentifier:identifier];
if([annotation isEqual:map1]){
annotationView.pinColor = MKPinAnnotationColorRed;
}
else {
if (!annotationView)
{
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
// if(fromSelectedTab==TRUE){
// annotationView.pinColor = MKPinAnnotationColorRed;
// annotationView.animatesDrop = NO;
// fromSelectedTab=FALSE;
// }
// else{
annotationView.pinColor = MKPinAnnotationColorGreen;
annotationView.animatesDrop = NO;
// }
annotationView.canShowCallout = YES;
// annotationView.dr
}
else {
annotationView.annotation = annotation;
}
}
//annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return annotationView;
}
MapObjects.h:
#interface MapObjects : NSObject<MKMapViewDelegate,MKAnnotation>
{
NSString *title,*subtitle;
CLLocationCoordinate2D coordinate;
}
#property(nonatomic,copy)NSString *title;
#property(nonatomic,copy)NSString *subtitle;
#property(nonatomic) CLLocationCoordinate2D coordinate;
-(MapObjects *)initwithCoordinate:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle;
#end
Use :
- (MKAnnotationView *)viewForAnnotation:(id <MKAnnotation>)annotation;
instead of creating a new MKPinAnnotationView. Or if it's in purpose you have to add somewhere the new annotation in your map.
Hope that will help
You should override MKMapiew method
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation (id<MKAnnotation>)annotation {
static NSString *identifier = #"PinAnnotation";
// map1 should be visible in method context
if ([annotation isEqual:map1]) {
MKPinAnnotationView *pinAnnotation = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
pinAnnotation.pinColor = MKPinAnnotationColorRed;// or any you want
return pinAnnotation;
}
return nil;
}
There you can determine specified annotation and set it desired color.
in viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
// There you should have selected "user" object and "users" array
...
// _annotations is declared in header
_annotations = [[NSMutableArray alloc] initWithCapacity:0];
for (UserObj *obj in users) {
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(0.f, 0.f);
coordinate.latitude = obj.latitude;
coordinate.longitude = obj.longitude;
MapObjects *userAnnotation = [[MapObjects alloc] initWithCoordinate:coordinate title:obj.name subtitle:nil];
[map addAnnotation:userAnnotation];
[_annotations addObject:userAnnotation];
}
...
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKPinAnnotationView *)view {
view.pinColor = MKPinAnnotationColorRed;
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKPinAnnotationView *)view {
view.pinColor = MKPinAnnotationColorGreen;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation (id<MKAnnotation>)annotation {
static NSString *identifier = #"PinAnnotation";
MKPinAnnotationView *pinAnnotation = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if(!pinAnnotation) {
pinAnnotation = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
}
pinAnnotation.pinColor = MKPinAnnotationColorGreen;
return pinAnnotation;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// You should keep your annotation objects in some array too because map.annotations won't return annotation in order that we need
// After you add annotation to map, add them to NSMutableArray too, [_annotations addObject:userAnnotation];
MapObjects annotation = _annotations[indexPath.row];// not sure that it return that exact annotation
[map selectAnnotation:annotation animated:YES];
}
I am trying to create draggable custom pin with Title popup with MapKit. but when I implement viewForAnnotation to make PIN appear as custom image, its disappears pop title as if I youch Pin on map it does not show titla popup,
while if I comments viewForAnnotation it works fine, but I want both things custom image and popup title when tap pin.
below is code
- (void)viewDidLoad
{
MKCoordinateRegion newRegion = MKCoordinateRegionMakeWithDistance(LocCoordinate, 20000, 20000);
DDAnnotation *point = [[DDAnnotation alloc] init];
[point setCoordinate:mapCenter];
[point setTitle:#"Where am I"];
[point setSubtitle:#"I am here"];
[self.mvTripMap addAnnotation:point];
[self.mvTripMap setRegion:newRegion animated:YES];
[super viewDidLoad];
}
-(MKAnnotationView *)mapView:(MKMapView *)MapView viewForAnnotation:(id<MKAnnotation>)annotation{
static NSString *cabAnnotationIdentifier=#"cabAnnotationIdentifier";
MKAnnotationView *annotationView=[MapView dequeueReusableAnnotationViewWithIdentifier:cabAnnotationIdentifier];
if(!annotationView){
annotationView=[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:cabAnnotationIdentifier];
annotationView.image=[UIImage imageNamed:#"start.png"];
annotationView.draggable = YES;
}
return annotationView;
}
DDAnnotation.h
#import <MapKit/MapKit.h>
#interface DDAnnotation : MKPlacemark {
CLLocationCoordinate2D coordinate_;
NSString *title_;
NSString *subtitle_;
}
// Re-declare MKAnnotation's readonly property 'coordinate' to readwrite.
#property (nonatomic, readwrite, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSString *subtitle;
#end
DDAnnotation.m
#import "DDAnnotation.h"
#implementation DDAnnotation
#synthesize coordinate = coordinate_;
#synthesize title = title_;
#synthesize subtitle = subtitle_;
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate addressDictionary:(NSDictionary *)addressDictionary {
if ((self = [super initWithCoordinate:coordinate addressDictionary:addressDictionary])) {
self.coordinate = coordinate;
}
return self;
}
#end
Just put annotationView.canShowCallout= YES; and it will work
updated code
-(MKAnnotationView *)mapView:(MKMapView *)MapView viewForAnnotation:(id<MKAnnotation>)annotation{
static NSString *cabAnnotationIdentifier=#"cabAnnotationIdentifier";
MKAnnotationView *annotationView=[MapView dequeueReusableAnnotationViewWithIdentifier:cabAnnotationIdentifier];
if(!annotationView){
annotationView=[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:cabAnnotationIdentifier];
annotationView.image=[UIImage imageNamed:#"start.png"];
annotationView.draggable = YES;
annotationView.canShowCallout= YES;
}
return annotationView;
}
I'm having trouble getting the MKAnnotationViews show up on the map in MapKit. I'm using iOS 7, and have now searched the forums and the web for many hours, trying different samples and setups.
Below I have the most basic setup possible (I think) to make it work. The app contains a single ViewController with a toolbar with a button on top, and the rest is the MapView. The button triggers the method zoomToUser:(UIBarButtonItem*)sender. Right-clicking and checking my outlets and delegates seem to be correct. I have some NSLog-statements being triggered to output some debug info.
First the VC:
#import "ViewController.h"
#import "Data.h"
#interface ViewController () <MKMapViewDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
- (IBAction)zoomToUser:(UIBarButtonItem *)sender;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.showsUserLocation = YES;
Data *ann = [[Data alloc] init];
[self.mapView addAnnotation:ann];
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self zoomToUser:nil];
}
-(IBAction)zoomToUser:(UIBarButtonItem *)sender
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(self.mapView.userLocation.coordinate, 2000, 2000);
NSLog(#"region: %f x %f",self.mapView.userLocation.coordinate.latitude,self.mapView.userLocation.coordinate.longitude);
[self.mapView setRegion:region animated:YES ];
NSArray *arr = self.mapView.annotations;
for(int i = 0, max = arr.count; i < max; i++)
{
id<MKAnnotation> annotation = arr[i];
NSLog(#"%d of %d: %# (%#)",i+1,max,annotation.title, [annotation class]);
}
}
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
NSString *reuseId = #"Test";
if([annotation isKindOfClass:[MKUserLocation class]])
{
return nil;
}
else if( [annotation isKindOfClass:[Data class]])
{
MKAnnotationView *annov = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
if(!annov)
{
annov = [[MKAnnotationView alloc]initWithAnnotation:annotation
reuseIdentifier:reuseId];
}
else
{
annov.annotation = annotation;
}
annov.canShowCallout = YES;
NSLog(#"Title: %#",annotation.title);
return annov;
}
else
{
return nil;
}
}
#end
And the Data class:
#import "Data.h"
#implementation Data
-(NSString *)title
{
return #"The title";
}
-(NSString *)subtitle
{
return #"A subtitle";
}
-(CLLocationCoordinate2D)coordinate
{
CLLocationCoordinate2D coordinate;
coordinate.latitude = 60.123456;
coordinate.longitude = 10.123456;
return coordinate;
}
#end
The Data.h:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface Data : NSObject <MKAnnotation>
#end
And the ViewController.h:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface ViewController : UIViewController
#end
As you can see the viewForAnnotation-method prints the annotations title in console when it's requested, and each time the map pans the area, it prints.
Pressing the BarButton and triggering the zoomToUser:-method logs to console that the map indeed has two annotations, the MKUserLocation and the one I added.
How come my MapView tells me it has the annotation, it asks for the view, it gets the view, but it does not show it?
In viewForAnnotation, the code is creating and returning an MKAnnotationView for annotations of type Data.
The MKAnnotationView class, by default, creates an empty view.
That is, its image property is nil and the view basically contains no content.
So, as-is, the annotation views are being created and added but they are invisible.
You can either:
Set the image property on the MKAnnotationView:
annov.image = [UIImage imageNamed:#"something"];
Or, simpler, create an MKPinAnnotationView instead which is a convenient subclass of MKAnnotationView that displays a pin image for you:
MKPinAnnotationView *annov = (MKPinAnnotationView *)[mapView dequeue...
if(!annov)
{
annov = [[MKPinAnnotationView alloc]initWithAnnotation:annotation
reuseIdentifier:reuseId];
annov.pinColor = MKPinAnnotationColorRed; //or Green or Purple
}
else
...
Unrelated:
You've created a custom annotation class Data which is fine but if all you need are the three properties title, subtitle, and coordinate, then you can just use the pre-defined MKPointAnnotation class which lets you set all the properties per-instance:
MKPointAnnotation *ann = [[MKPointAnnotation alloc] init];
ann.title = #"The title";
ann.subtitle = #"A subtitle";
ann.coordinate = CLLocationCoordinate2DMake (60.123456, 10.123456);
[self.mapView addAnnotation:ann];