I have a MKMap with a series of MKAnnotations, all of which are red which is fine. I have selected "show user location" in IB and to change the MKAnnotation from red to blue, I have the code in my viewForAnnotation method:
if (annotation == theMap.userLocation)
return nil;
All is good and the app works fine, but if the user inadvertently taps the blue userlocation dot I get the following crash:
2012-02-01 20:43:47.527 AusReefNSW[27178:11603] -[MKUserLocationView setPinColor:]: unrecognized selector sent to instance 0x79b0720
2012-02-01 20:43:47.528 AusReefNSW[27178:11603] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MKUserLocationView setPinColor:]: unrecognized selector sent to instance 0x79b0720'
*** First throw call stack:
If I remove the above code, all works well but the pin is red. I perfer to have the blue icon but as yet have not discovered why the crash. Any ideas would be appreciated. Thanks.
SOLVED! Thanks Marvin and heres the code incase anyone finds it useful. In a nutshell, I had to first check to see if the MKAnnotation was of MyAnnotation Class or of MKUserLocation Class.
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKPinAnnotationView *)view
{
theAnnotationSelected = [[mapView selectedAnnotations] objectAtIndex:0];
if ([theAnnotationSelected isKindOfClass:[MyAnnotation class]] )
{
view.pinColor = MKPinAnnotationColorGreen;
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKPinAnnotationView *)view
{
if ([theAnnotationSelected isKindOfClass:[MyAnnotation class]] )
{
view.pinColor = MKPinAnnotationColorRed;
}
For Current User Location go to MKMapView property and make selection on Shows User Location in XIB.
then Implement MKMapViewDelegate in your controller..and write this method in your controller
-(MKAnnotationView *)mapView:(MKMapView *)pmapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil; //return nil to use default blue dot view
if([annotation isKindOfClass:[MKAnnotationClass class]])
{
//Your code
}
}
and this
- (void)mapView:(MKMapView *)mapView1 didSelectAnnotationView:(MKAnnotationView *)customAnnotationView
{
if(![annotation isKindOfClass:[MKUserLocation class]])
{
//Your code
}
}
Using this you can see blue dot on User Location..
You will want to check the class of the annotation in
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
Then do the following..
id *annotation = view.annotation;
if (![annotation isKindOfClass:[MKUserLocation class]]) {
//Normal Code here
}
This solution works in iOS7 to suppress the callout view, but it does not stop the user from selecting the blue dot. How to suppress the "Current Location" callout in map view
I have yet to find a way to disable selection of the current location dot.
It isn't so much a workaround as a "way to deal with it", but I zoom the map in to focus on certain types of annotations when tapped. If the user happens to be located right on top of one, the zooming helps put some distance between the blue dot and my annotation, making it easier to tap.
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
if([view.annotation isKindOfClass:[SpecialClass class]]){
SpecialClass *cluster = (SpecialClass *)view.annotation;
if(testCriteria){
[self.mapView setRegion:MKCoordinateRegionMakeWithDistance(cluster.coordinate, cluster.radius, cluster.radius) animated:YES];
}
}
I had the same issue such that when a user would tap the MKUserlocation "blue dot" the application would crash. I am using DDAnnotation by Ching-Lan 'digdog' HUANG. The fix I found was
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
id annotation = view.annotation;
if (![annotation isKindOfClass:[MKUserLocation class]]) {
//Your Annotation Code here
}
}
Related
How can I block user interaction with the my current location pin? I have problem like this: I have many pins on my map and if they are close and they are around "my current location" pin, that pin takes the click event I wan to block it. i don't want the bubble "Current Location" to be shown.
I know it is something with *pinView.canShowCallout = NO; but how do I know what pin is my location??
Thanks
this should give you what you need..
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
if ([annotation isKindOfClass:[MKUserLocation class]]) {
view.canShowCallout=NO;
}
}
Let me know if it works.. :)
this doesn't work because you need to select it at least one to work it out, but thanks anyway it helped very much for the search starting point :)
I did it with this code:
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
{
for(int i = 0; i< [views count]; i++)
{
if([[[[views objectAtIndex:i] class] description] isEqualToString:#"MKUserLocationView"])
{
((MKAnnotationView*)[views objectAtIndex:i]).canShowCallout = NO;
}
}
}
you must find the view and them apply it.
also you need to put this:
if ([annotation isKindOfClass:[MKUserLocation class]]) {
[mapView viewForAnnotation:annotation].canShowCallout = NO;
return [mapView viewForAnnotation:annotation];
}
in :- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
I'm trying to make a custom annotation view able to respond to touches without success.
Thanks to this question I was able to made an annotation view close to what I want customize callout bubble for annotationview? also seen this How to capture touches and NOT dismiss the callout? but the problem is quite different
The first thing I've done so far is subclassing an MKAnnotationView and override the -setSelected:animated: method
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if(selected)
{
MyCallOut * callOut=[MyCallOut createMyCallOut];
callOut.tag=555;
[self.superview addSubview:callOut];
}
else
{
// [[self viewWithTag:555] removeFromSuperview];
//Remove my custom CallOut
}
}
The problem is that the map view is eating all the touches event, my custom callout has two buttons but no action is triggered pressing them.
In one of my experiment I've tried to add the callout view to the MKAnnotationView superview (the mapView) everything seems to be fine while I scroll, but If I zoom the callout moves around.
you have to add call out accessory view in map annotation
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation {
MKPinAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil ) pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return pinView;
}
else {
[mapView.userLocation setTitle:#"I am here"];
}
return pinView;
}
and for click event of your call out
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
}
Solved looking to this link Custom annotation and callouts, the other tricky part is implement a correct way to press button on the fake callout. I managed this part creating a boolean value that understands the number of annotation/parentAnnotation on screen and choose when one could disappear or not.Just need to make the CalloutAnnotation available to selection.
I want to display a 2 line label in the callout for current location.
MKUserLocation and not MKAnnotation
Can anybody help with how is it possible?
Am sure It would be possible with custom Callout.. But not sure how to create it for MKUserLocation.
In the viewForAnnotation method you could try this:
- (MKAnnotationView *)map:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>) annotation{
if(self._mapView.userLocation==annotation){
self._mapView.userLocation.title=#"some text";
self._mapView.userLocation.subtitle=#"some text";
return nil;
}
}
Hope this helps.
I assume you can create custom annotation callout and want to use instead of default callout for userlocation. To get this done one need to get reference of current location MKAnnotationView. One can get this reference anywhere but it is better to get it as soon as user location is determined.
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKAnnotationView* annotationView = [mapView viewForAnnotation:userLocation];
annotationView.canShowCallout = NO;
//your customization here
}
Or use following method
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
MKAnnotationView *aV;
for (aV in views) {
if ([aV.annotation isKindOfClass:[MKUserLocation class]]) {
MKAnnotationView* annotationView = aV;
annotationView.canShowCallout = NO;
//your customization here
}
}
}
and if want to change in canShowCallout property in runtime then one can use following
for (AnnotationClass* annotation in mapView.annotations)
{
if([annotation isKindOfClass:[MKUserLocation class]] )
{
MKAnnotationView* annotationView = [mapView viewForAnnotation:annotation];
annotationView.canShowCallout = NO;
//your customization here
}
}
I'm trying to put a little button in my AnnotationViews to show some info about some places on a map. Sounds super basic? Well. I must be an idiot then...
I've looked at multiple examples, searched the whole internet, and I have ripped of 95% of my hair. It just doesn't work!
-(MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)theAnnotation;
{
MKAnnotationView * annotationView = nil;
if([theAnnotation class] == [MyAnnotation class])
{
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:theAnnotation reuseIdentifier:#"annotation"];
annotationView.canShowCallout = YES;
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.enabled = YES;
}
return annotationView;
}
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control;
{
NSLog(#"push %#", control);
}
Can some one please tell me why calloutAccessoryControlTapped never gets called?
I get a nice and pretty annotation, but when I tap the blue button it just closes. I have tried adding a target to the button, nothing.
Please help me!
PS: I know I should reuse old annotation view and stuff, but i stripped all code that wasn't necessary to be sure that there wasn't something else that was screwing thins up.
Make sure you have correctly set the delegate responding to the MKMapViewDelegate Protocol.
Also, make sure that all the views and superviews have userInterActionEnabled set to YES.
I have tried it both on an actual device (iPad) and the iPhone simulator (ios 4)
I see the map but no Apple headquarters (blue pin) even if I zoom in.
In my OnViewLoad function I have:
mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
mapView.showsUserLocation=TRUE;
mapView.mapType=MKMapTypeHybrid;
[self.view insertSubview:mapView atIndex:0];
In your -mapView:viewForAnnotation: method, return nil if the annotation is a userLocation object:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
if ([annotation isMemberOfClass:[MKUserLocation class]]) {
return nil;
}
// your normal code
}
This is needed to make sure, the iOS default implementation is used to show the blue userLocation dot.