I have implemented one map application in which i have display pin animation for current location.When i click on the pin at that time annotation view will open. But i want to display
annotation view without clicking on pin.Is it possible if possible then please give me idea about that.
Thanks in advance.
Try out:
It seems that [mapView selectAnnotation:annotation animated:YES] works too.
Hope this helps.
You just need to find your MKAnnotationView instance you want to select and call -setSelected:animated:.
For example, you can loop your annotations of an MKMapView like this:
for (YOURCLASSHERE *a in mapView.annotations) {
// Your current position (if shown) is an annotation as well. Thus check for the right class!
if ([a isKindOfClass:[YOURCLASSHERE class]]) {
// insert some smart if statement here, if you have multiple annotations!
[[mapView viewForAnnotation:a] setSelected:YES animated:YES];
}
}
YOURCLASSHERE is your class which implements the MKAnnotation protocol.
Of course the loop is superfluous if you already know your annotationView.
We can show the annotation with out clicking on it. Use the following code:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
static NSString *identifier = #"Pin";
MKPinAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
pin.canShowCallout = YES;
[pin setSelected:YES animated:NO];
return [pin autorelease];
}
Related
I have a map view with pins that when the user selects a pin it goes to a detail screen for that pin. I also have a table view that when the user selects an item it goes to the same type detail view.
I am adding the multiple pins in mapview through array. I have added button to the accessory view,
Here's the problem ...
when I tap the button pin selection takes him to the detail view for a different pin. But in the table view it still works fine..anyone pls help me with this...?
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKPinAnnotationView *newAnnotation = nil;
if([annotation.title isEqualToString:#"You are here."])
{
newAnnotation = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"greenpin"];
newAnnotation.pinColor = MKPinAnnotationColorGreen;
}
else
{
newAnnotation = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"redpin"];
newAnnotation.pinColor = MKPinAnnotationColorRed;
UIButton *pinButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinButton.tag = indexvar;
[newAnnotation addSubview:pinButton];
newAnnotation.canShowCallout = YES;
newAnnotation.rightCalloutAccessoryView = pinButton;
newAnnotation.calloutOffset = CGPointMake(-5, 5);
indexvar++;
return newAnnotation;
[pinButton release];
}
newAnnotation.animatesDrop = YES;
newAnnotation.canShowCallout = YES;
return newAnnotation;
}
- (void)mapView:(MKMapView *)wikiMapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSInteger selectedIndex = ((UIButton *)control).tag;
NSLog(#"Property Index : %d ",selectedIndex);
DetailView = [[PropertyDetails alloc] initWithNibName:#"PropertyDetails" bundle:nil];
DetailView.propertyReference = [PropertyReferenceArr objectAtIndex:selectedIndex];
DetailView.propertyTitle = [propertyTitlesArr objectAtIndex:selectedIndex];
DetailView.propertyPrice = [propertyPriceArr objectAtIndex:selectedIndex];
DetailView.propertyBedrooms = [propertyBedroomsArr objectAtIndex:selectedIndex];
DetailView.propertyLatitude = [propertyLatitudesArr objectAtIndex:selectedIndex];
DetailView.propertyLongitude = [propertyLongitudesArr objectAtIndex:selectedIndex];
DetailView.propertyDefaultImage = [PropertyImageArr objectAtIndex:selectedIndex];
DetailView.propertyStatusId = [PropertyStatusArr objectAtIndex:selectedIndex];
[self.navigationController pushViewController:DetailView animated:YES];
[DetailView release];
}
In viewForAnnotation, the way you are setting the button tag using an ivar counter (indexvar) assumes that the delegate method will get called only once and in the order that the annotations are added (which you are presumably doing in index order in some loop).
The above assumption is not safe to make and not recommended. For example, the delegate method can definitely be called multiple times for the same annotation if the map view needs to re-display an annotation after it comes back into view because the user panned or zoomed back.
Instead of using button tags, embed the information you need into the annotation class itself and set that information when you add the annotation.
At a minimum (but still not recommended), what you could do is add a propertyIndex property to your annotation class and set it equal to the array index (of say the PropertyReferenceArr array) you are creating the annotation from.
A better solution, based on the numerous arrays you are using in calloutAccessoryControlTapped, is to create a proper class object to hold all the properties (of your real-estate "Properties" objects) and then have a single array to hold them (instead of a separate array for each attribute).
This class could itself conform to MKAnnotation so you don't need to create a separate, explicit annotation object (you can just add the property object itself to the map).
Then in calloutAccessoryControlTapped, you just cast view.annotation to your custom class and you instantly have access to all the annotation/Property data without any need for a tag or array index.
The comment #naveen makes about your addSubview line is also valid (though it's not related to the issue). You should definitely remove that.
Also, in viewForAnnotation, calling [pinButton release]; after the return is pointless. That code will never run (which is good because if you put it before the return, app will crash since pinButton is autoreleased).
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
myAnnotation *annView = view.annotation; // myAnnotation is my custom class for annotations
// now in annView you have the exact annotation whose accessorybutton is clicked now you can do whatever you want with it.
NSLog(#"title = %#",annView.title);
}
Rather then setting the button tag you can use the title or subtitle of the annotation for futher comparision or whatever you want
In your code you are using
[newAnnotation addSubview:pinButton]; // i think this is wrong you should only add it to accessory view
I have MKMapView with MKPlacemark on it. When showing the map, I'm showing place mark's title.
Everything is fine until now.
I want to disable hiding title when user touches it.
I tried to add
myMapView.userInteractionEnabled = NO;
myMapView.multipleTouchEnabled = NO;
Which helps, but completely disables interaction with map. I want to leave a possibility to zoom in/out and moving the map.
Instead of creating PIN, create your custom annotation. In custom annotation create the view with all the info that you want to present to user, and disable the place mark. By that you are not suppose to handle taps but you will show all the static/dynamic info attached to one lattitude/longitude.
The following code did the trick
for (UIGestureRecognizer *g in [myMapView gestureRecognizers])
[myMapView removeGestureRecognizer:g];
In MapKit Delegate method try bellow code
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *defaultPinID = #"com.invasivecode.pin";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[yourMapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
if (annotation == yourMapview.userLocation)
return nil;
pinView.pinColor = MKPinAnnotationColorRed;
pinView.userInteractionEnabled = NO;
//pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
return pinView;
}
here if you use your placemark with this logic may its work....
hope,this help you...
:)
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 setup an NSMutableArray of objects derived from a class that conforms to the MKAnnotation protocol. I have setup setup title and subtitle for the annotation and have successfully added them to the MKMapView using:
[[self customMapView] addAnnotations:locationArray];
What I want to do now is animate the pins dropping, initially I thought I could do that with Option1, using this everything works, but the pins don't do an animated drop.
// Option1
// WORKS FOR: pinColor YES, animatesDrop NO, LABEL YES
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
for(MKPinAnnotationView *eachView in views) {
[eachView setAnimatesDrop:YES];
[eachView setPinColor:MKPinAnnotationColorPurple];
}
}
My next guess was to try Option2, this seems to work very well but I have two issues. The title and subtitle don't show up, my custom annotation object is getting passed in (I can see it in the debugger) but the information contained is not making it across to the new pin. Secondly this creates a new set of MKAnnotationViews, what happens to the old ones, are there and issues with memory leaks?
// Option2
//FOR: pinColor YES, animatesDrop YES, LABEL NO
- (MKAnnotationView *) mapView: (MKMapView *) mapView viewForAnnotation: (id<MKAnnotation>) annotation {
MKPinAnnotationView *pin = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier: #"annotation_ID"];
if (pin == nil) {
pin = [[[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: #"annotation_ID"] autorelease];
} else {
pin.annotation = annotation;
}
pin.pinColor = MKPinAnnotationColorRed;
pin.animatesDrop = YES;
return pin;
}
EDIT: I have solved the missing title & subTitle by adding pin.canShowCallout = YES;
MKPinAnnotationView is a subclass of MKAnnotationView.
MKAnnotationView is a generic annotation view for which you have to provide the image and animation if desired.
MKPinAnnotationView is a convenient subclass of MKAnnotationView which automatically provides a pin image in a selected color and an animation of the pin dropping onto the map. You set the animatesDrop property when creating the view in viewForAnnotation and it will handle the animation automatically from there.
If you don't implement viewForAnnotation, a standard red pin with no animation is displayed.
By the time didAddAnnotationViews is called, the automatic animation has already happened and setting that property there has no effect.
If however you want to create a custom animation different from the default drop animation that MKPinAnnotationView provides, you could do that in didAddAnnotationViews. The view will already be at its final destination point so you save that and then animate it from a different point to that destination.
If you're happy with the default drop animation that MKPinAnnotationView provides, you don't need to implement didAddAnnotationViews. That delegate method is more useful for doing other things that you might need to do when all the annotation views are actually in place.
For your pins to show the title, set canShowCallout to YES where you set animatesDrop.
Not sure what you mean by "this creates a new set of MKAnnotationViews". In the viewForAnnotation method, you are providing a view (MKPinAnnotationView) for the MKAnnotation object. They are not the same thing.
Also, the viewForAnnotation method works like the cellForRowAtIndexPath method for UITableView where annotation views can get recycled which is why it's important to set MKAnnotation-specific information in the view every time (such as the annotation property).
Here's the most simple solution I could find. What it does is drops a single pin on the UIMapView in viewDidLoad event.
The project references MapKit framework
The view have the following import:#import <MapKit/MapKit.h>
The view controller implements MKMapViewDelegate protocol
The view controller implementation contains:
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id ) annotation
{
MKPinAnnotationView *newAnnotation = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"annotation1"];
newAnnotation.pinColor = MKPinAnnotationColorGreen;
newAnnotation.animatesDrop = YES;
newAnnotation.canShowCallout = NO;
[newAnnotation setSelected:YES animated:YES];
return newAnnotation;
}
The viewDidLoad contains:
CLLocationCoordinate2D geos = CLLocationCoordinate2DMake(0.2344, 45.324);
MKPlacemark* marker = [[MKPlacemark alloc] initWithCoordinate:geos addressDictionary:nil];
[mapView addAnnotation:marker];
[marker release];
Update Swift3:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let pinAnnotation = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "PinAnnotation")
pinAnnotation.pinTintColor = .green;
pinAnnotation.animatesDrop = true;
pinAnnotation.canShowCallout = false;
pinAnnotation.setSelected(true, animated: true)
return pinAnnotation
}
I would like to emulate the 'Drop Pin' feature in the Maps application. I have a mapview in my controller that I am able to add a MKPlacemark to. It doesn't respond to user action though. Can I emulate the dropped pin with stock classes or do I need to subclass an MKAnnotation View?
EDIT2:
Here's the code I'm trying, which I think should work. It drops the pin, and I can change the color but it can't be moved.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id
<MKAnnotation>)annotation
{
MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:nil];
[pinView setDraggable:YES];
[pinView setAnimatesDrop:YES];
[pinView setPinColor:MKPinAnnotationColorGreen];
return pinView;
}
Here ya go: (iPhone) how to implement draggable pins using OS 4.0 MapKit?
With iOS 4 it's natively possible. Did you add an custom annotationView or a MKPinAnnotationView?
Look a the "draggable" property in MKAnnotationView.