MKAnnotationView - Lock custom annotation view to pin on location updates
Asked Answered
E

3

30

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];
    }
}
Eurus answered 17/6, 2011 at 23:58 Comment(5)
@JARinteractive - I think you're the resident expert, since you wrote the blog post I'm following. Do you have any ideas?Eurus
The project you link to is missing a couple of PNGs, map_marker and map_marker@2x. Can you include and replace the zip? Also, the naming of your setAnnotation... method made me feel better about my method naming when I get frustrated.Auricula
Ha! I guess I forgot to clean it up. Yes, definitely the naming convention I go with after five days of pulling my hair out. I just added the .png's and re-uploaded. Take a look, and thanks for giving this a look!Eurus
The link for the example code doesn't work for me. There are any mirror?Sansen
Viewing your code, I think the problem could be in the way you are dealing with the location. Executing the code at the beginning it gives the same location 19 times, after that never again. Why don't you use CoreLocation instead of NSNotificationCenter?Sansen
V
33

custom callout

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

Vernon answered 9/9, 2011 at 15:19 Comment(4)
Thanks Jacob, your code is the first example I see of a custom callout loaded from a .xib. Great answer.Jugendstil
Oh wow, the megaupload takedown affected me personally. I'll clean it up and put it on github or something tonight.Vernon
sir i add some detail for pin click how to addClearance
i am not able to implement this code in my project can anybody help meDarkness
A
2

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.

Auricula answered 26/6, 2011 at 0:34 Comment(2)
Definitely one way to go about this. I think the reason why @JARinteractive performs everything in drawRect: instead of just creating an image is because the arrow pointing down to the pin needs to be dynamic. If the pin is towards the left of the screen, the callout annotation's arrow will be drawn over there. Same thing if the pin annotation is on the right side of the screen. Also, one thing that's nice about the standard callout, is that it animates with the pin from one point to another. Doing it your way means I'd have to clear the image before the move, then make it appear again after.Eurus
I think using the base MKAnnotationView with an image, the framework will draw the callout arrow.Auricula
S
2

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.

Sansen answered 13/11, 2011 at 23:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.