[_mapView selectAnnotation:sannotation animated:YES];
It appears not always, so I don't understand what's the reason for it.
How to fix it?
Before selecting any annotation deselect all annotations on mapView.
for (id<MKAnnotation> annotation in mapView.annotations)
[mymap deselectAnnotation:annotation animated:NO];
I had same issue when along with default callout, I had implemented custom callouts. Though it is not a perfect solution it served the purpose.
Related
I have an MKMapView. To change the displayed region I use
[self.mapView setRegion:region animated:YES];
The strange is that on simulator the region is changed with animation, but on device the change is immediate and not animated.
I change the region after a long tap on the map...
This behavior drive me crazy and I can't able to solve it...
Thanks...
You need to slow down setRegion by using the following code
[self performSelector:#selector(setMapRegion) withObject:nil afterDelay:3.0];
-(void) setMapRegion
{
[self.mapView setRegion:region animated:YES];
}
If you load the map on device and iOS 6+ you'll experience a bit of delay till the tiles are loaded so the best thing to do is to try delaying the region change.
The map is not responsive even you set the animation it won't appear that clearly to you,it would look like it's not making any animation.
MKMapView calls its delegate method mapViewDidFinishLoadingMap: once the map has loaded all the necessary tiles and is ready to use. You should call setRegion:animated: there.
Update #5 I guess it's bounty time. 100+ views and no one's taken a stab, even with the code sample I've posted. How about some reputation points!
Update #4This is a pretty complicated question, so I created a new tab based project which just includes the parts of my app I'm having trouble with here. You can download it from: http://www.servinitup.net/CustomCalloutAnnotation.zip
Feel free to open it up (need to add your own bundle identifier to run it on your phone) and play around with it, and see if you can get that darned callout annotation to move with the pin!
Update #3 Tried making setAnnotation a public method of the tutorial's CalloutMapAnnotationView and calling that directly. Didn't have any luck. Despite little oddities that occurred, the only thing that moved was the little triangle portion of the callout. I could not get the entire callout to move.
Update #2 Still not much luck, but have now been looking for ways to programmatically create a "pinch to zoom" and then undo it immediately, so the user never sees a change. Hoping that doing this programmatically will have the same effect as doing it manually, and the callout annotation will pop back to it's parent. Any ideas?
Update #1 After playing around here's where I've gotten:
- replaced self.calloutAnnotation.coordinate = coords; with self.calloutAnnotation.latitude = coords.latitude;self.calloutAnnotation.longitude = coords.longitude;
- With that changed, if I slightly pinch the map to zoom in or out after the pin has been updated, the callout annotation animates to the correct position, right over the pin.
So now I need to figure out how to get this to happen without the user having to actually pinch to zoom.
Original Post
I, along with other SO users, are using this awesome solution to create a custom callout annotation:
http://blog.asolutions.com/2010/09/building-custom-map-annotation-callouts-part-1/
When you use a standard callout (annotationview.canShowCallout = true) and the pin moves around the screen as the location is updated, the standard callout tracks right along with the pin, as if they're locked together.
When using the custom callout solution above, when my pin moves around after location updates, the callout annotation stays in it's original location. Of course, I'd like to mimic the iOS standard and have the custom callout annotation track along with the pin.
Here's the code I have so far, that's successfully moving the annotation view, but not the custom callout annotation view:
/* core location broadcasts a notification, and my view controller listens to that notification and calls locationManagerDidFindLocation */
- (void)locationManagerDidFindLocation:(NSNotification *)notif {
CLLocation *location = [notif.userInfo objectForKey:#"location"];
CLLocationCoordinate2D coords = [location coordinate];
MKCoordinateSpan span = MKCoordinateSpanMake((5/69), (5/69));
MKCoordinateRegion region = {coords, span};
// if we don't have a current location yet, create one, place it on the map, and adjust the map's region
// otherwise, update the annotation placement and map position in a smooth animation
if (self.currentLocationAnnotation == nil) {
self.currentLocationAnnotation = [[CurrentLocationAnnotation alloc] initWithCoordinate:coords andTitle:#"My Title" andSubtitle:#"My subtitle"];
[self.mapView addAnnotation:self.currentLocationAnnotation];
[self.mapView setRegion:region animated:true];
[self.mapView regionThatFits:region];
} else {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.45];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
// this moves my annotation view perfectly
self.currentLocationAnnotation.coordinate = coords;
// ******* this is where my problem is
// ******* this custom callout annotation view stays
// ******* in it's original place, even though it's
// ******* parent annotation view is moving around the screen
self.calloutAnnotation.coordinate = coords;
[self.mapView setRegion:region animated:true];
[self.mapView regionThatFits:region];
[UIView commitAnimations];
}
}
I created a project based on your CalloutMapAnnotationView demonstrating a IB based solution. Arrow keys animate motion of the location annotation and it's callout annotation. The callout now also automatically resizes based on the supplied contentView, and the view is loaded from a separate nib. Good luck!
https://github.com/jacobjennings/JJMapCallout
I know you aren't going to like this answer, but it works. The sample you linked to just draws a custom image in the overlay through the most difficult way possible (drawRect:). Have you considered rendering your overlay once into a UIImage, and just setting the image property on a very simple MKAnnotationView? Even if you need to change the content periodically, like updating the number of friends at a bar, you can redraw the image when the change occurs and update the appropriate MKAnnotationView.
I review your code and my recommendation is to create a new custom MKAnnotationView and encapsulate on it both views (the pin and the callout).
But for your current code consider read the approved response this question: MKMapView moving Annotations Automatically - animate them?
Cheers.
*Note this works perfectly in xcode and is only a problem on a iPhone running IOS 4.2.1
When I set the map to fit a region it does not refresh the map until I touch the screen. The bit of code I use is:
MKCoordinateRegion scaledRegion = [mapView regionThatFits:region];
[mapView setRegion:scaledRegion animated:YES];
This does move the map to the correct region which I can see when I touch the screen but until I touch the screen I get a grey screen with lots of grid lines across it.
It almost seems like the map is waiting for some sort of refresh event. I have also tried the following code with no success.
MKCoordinateRegion scaledRegion = [mapView regionThatFits:region];
[mapView setRegion:scaledRegion animated:YES];
[mapView setCenterCoordinate:mapView.region.center animated:NO];
It is also worth noting this is running in a thread.
Thanks in advance for any help.
Very weird I have turned off the animation with the following code
[mapView setRegion:scaledRegion animated:YES];
to
[mapView setRegion:scaledRegion animated:NO];
And it has started working? I do not understand why?
Is it possible to use MKPinAnnotationView controls in a application that has nothing to do with maps.
I do not want to use MKMapView, I just want to reuse the MKPinAnnotationView control and be able to drop it at a specific screen coordinate.
Thanks,
Cristian
Well, it derives from UIView so it seems possible in theory, but it may not behave properly if its superview isn't a MKMapView. I would try it and see what happens (and let the rest of us know).
Alternatively, it wouldn't be too hard to create your own UIView subclass that behaves very similarly to the MKPinAnnotationView. (I would probably subclass UIControl since you probably want to be able to respond to user events.)
EDIT: I just tried a very basic implementation and it seems to work fine. Here's the code I used in my view controller. MyAnnotation is a very simple class that implements the MKAnnotation protocol.
- (void)viewDidLoad {
[super viewDidLoad];
MyAnnotation *annotation = [[[MyAnnotation alloc] init] autorelease];
MKPinAnnotationView *pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:nil] autorelease];
pinView.center = self.view.center;
[self.view addSubview:pinView];
}
Another update: Well, the pin displays, but it's not draggable even if draggable = YES, and the callout doesn't appear even if canShowCallout = YES. This makes sense given that these behaviors are actually controlled by the map view, and not the actual pin view.
So if you just want to display a pin with a shadow on your view, it works great. If you want some of the functionality you get when the pin is displayed in a map view, you have to implment it yourself in your view or view controller.
Ok, so I've got some issues with my MapKit annotations.
First of all, I want a callout for each annotation. I can't find out how to do this at all! :( I have two NSStrings (name of the place and a short description). Then I need to be able to log the click on the callout - so I can launch a disclosure view.
Secondly I want to change the view for the user location annotation.
At the moment all annotations are set to the "default" pin annotation view by way of this code:
- (MKAnnotationView *) mapView:(MKMapView *)myMapView viewForAnnotation:(id <MKAnnotation>) annotation{
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentloc"];
annView.animatesDrop=TRUE;
return annView;
}
I would prefer to have the user location annotation set to the default blue pulsing circle thing, but at least I want to be able to change the pinColor property to a different color, so the user can distinguish between their own location and the results of their search.
I hope somebody can help me.
Thank you.
I think you should consider using showsUserLocation to depict your users location - it's the standard UI for the platform and helps people get a consistent experience across apps. Sure you can come up with some custom annotation for user location but why re-invent what people are used to seeing on the maps app and on many 3rd party apps?
You should take the time to review Apple's code samples for MapKit everything you need to do is there. This one in particular is a good starting point for you:
http://developer.apple.com/iphone/prerelease/library/samplecode/MapCallouts/Introduction/Intro.html
hmm... the problem was i didn't know which annotation was the one being used by current location. Its ok - I've found it now. Something like if(annotation == mapView.userlocation){ return nil; } or similar. :) Thanks for your help though