I have class
#interface MyLocation : NSObject <MKAnnotation>
#property (copy) NSString *name;
#property (copy) NSString *address;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, strong) UIImage *banner;
#property (nonatomic, strong) NSString *descr;
When I add location on map i want that method - (MKAnnotationView*) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation show banner .... how can i do this?
- (MKAnnotationView*) mapView:
(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[MyLocation class]]) {
MKPinAnnotationView *annotationView = (MKPinAnnotationView*)
[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.image = [UIImage imageNamed:#"Image2.jpg"];
return annotationView;
}
return nil;
}
this method change all annotation pins but i need differed images for each annotation.
Thanks for help!
You have to use MKAnnotationView for custom pins, since MKPinAnnotationView always displays the "default" pins.
custom CLASS MKAnnotationView, and U can change the pins
see the sample code from apple:map callouts
Related
I have a custom annotation view class which is like
#interface MyAnnotationView : MKAnnotationView
#property (nonatomic, strong) UIImageView *imageView;
#end
and then I use it in the MKMapView like :
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKAnnotationView *annotationView = nil;
MyAnnotationView *view = (MyAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:MyAnnotationViewIdentifier];
if (view == nil) {
view = [[MyAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:MyAnnotationViewIdentifier];
}
view.imageView.image = myImage;
annotationView = view;
return annotationView;
}
This code works as expected till iOS 11, but in iOS 12 I dont see the image anymore. What am I missing? Any tips appreciated.
In my iOS app I have a MapView and I have a custom Annotation (extends MKAnnotation).
I set an icon image for each annotation depending on it's type. When I first load up the map view, all the images are correct, but as you move the view around the images start to change to different ones.
It's almost like the OS is recycling annotations and bringing them back as they reappear on the screen, but with the wrong image.
Does anyone know how to fix this? Thanks for your help.
Here is my delegate method:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
if ([annotation isKindOfClass:[CustomAnnotationView class]]) {
CustomAnnotationView *customAnnotation = (CustomAnnotationView *)annotation;
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomAnnotation"];
if (annotationView == nil) {
annotationView = customAnnotation.annotationView;
}
else{
annotationView.annotation = annotation;
}
return annotationView;
}
else{
return nil;
}
}
Here is what my object looks like:
#interface CustomAnnotationView : NSObject<MKAnnotation>
#property (nonatomic,readonly) CLLocationCoordinate2D coordinate;
#property (copy, nonatomic) NSString *title;
#property (copy, nonatomic) NSString *subtitle;
#property (weak, nonatomic) Thing *thing;
-(id)init:(Thing *)thing;
-(MKAnnotationView *) annotationView;
-(void)setDistance:(CLLocationCoordinate2D)point;
#end
I'm using an array of Locations (stored online) which have a LocationID, lat, long, name, PinNumber and UserId.
Steps : I load the complete locations array of the selected user
I create pins with that array ( a simple for loop that uses the name, location, etc.)
Sadly, the MKPointAnnotation can only have a name and coordinates, and this is where my problems appears.
When my user selects a pin and uses the annotation (correct me if i'm wrong, that is the little info button inside the selected pin), he is redirected to another page where he can edit that location, and I can't find it in the database because i can't get the ID of the location.
I tried using NSInteger index = [mapView.annotations indexOfObject:view.annotation]; and check that index in my location array, but it just doesn't match.
What can i do to get my object back from that pin ? Or any workaround that gets the job done really.
You can subclass MKAnnotation and add your object ID to it as follows:
In CustomAnnotation.h,
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface CustomAnnotation : NSObject <MKAnnotation>
#property (nonatomic, retain) NSString *title;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, retain) NSNumber *objectID;
- (id)initWithTitle:(NSString *)newTitle id:(NSNumber *)objectID location:(CLLocationCoordinate2D)location;
- (MKAnnotationView *)annotationView;
#end
In CustomAnnotation.m,
#import "CustomAnnotation.h"
#implementation CustomAnnotation
- (id)initWithTitle:(NSString *)newTitle id:(NSNumber *)objectID location:(CLLocationCoordinate2D)location
{
self = [super init];
if(self)
{
// Initialization code
_title = newTitle;
_coordinate = location;
_objectID = objectID;
}
return self;
}
- (MKAnnotationView *)annotationView
{
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:self reuseIdentifier:#"MyCustomAnnotation"];
// Your settings
annotationView.draggable = NO;
annotationView.enabled = YES;
return annotationView;
}
#end
Also, in mapView:viewForAnnotation:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
// Customise all annotations except MKUserLocation
if([annotation isKindOfClass:[CustomAnnotation class]])
{
CustomAnnotation *point = (CustomAnnotation *)annotation;
MKAnnotationView *pointView = (MKAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:#"MyCustomAnnotation"];
if(pointView == nil)
pointView = point.annotationView;
else
pointView.annotation = annotation;
...
// do something with point.objectID
return pointView;
}
else
return nil;
}
You can subclass MKPointAnnotation and create a new property with your object
#interface CustomPointAnnotation : MKPointAnnotation
#property (nonatomic, strong) CustomObject* object;
#end
Now whenever you deal with an <MKAnnotation>, cast it to a CustomPointAnnotation* and set/get the object property.
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 would like to have a MKMapView showing annotations with disclosure-buttons which lead to a view controller like the Golden Gate Bridge annotation in this Apple sample app.
I load the coordinates from a plist and the annotations appear correctly with title/subtitle but the method
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
has no effect.
I guess that I somehow have to link the annotations with the pinannotations?
MapViewController.h:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "Annotation.h"
#interface MapViewController : UIViewController<CLLocationManagerDelegate, MKMapViewDelegate>
#property (strong, nonatomic) CLLocationManager *location;
#property (nonatomic, retain) NSArray *data;
#end
MapViewController.m:
#import "MapViewController.h"
#interface MapViewController ()
#property (nonatomic, weak) IBOutlet MKMapView *mapView;
#end
#implementation MapViewController
#synthesize data;
#synthesize location, minLatitude, maxLatitude, minLongitude, maxLongitude;
- (void)viewDidLoad
{
NSString *dataPath = [[NSBundle mainBundle] pathForResource:#"City" ofType:#"plist"];
self.data = [NSArray arrayWithContentsOfFile:dataPath];
for (int i = 0; i < data.count; i++) {
NSDictionary *dataItem = [data objectAtIndex:i];
//Create Annotation
Annotation *building = [[Annotation alloc] init];
building.title = [dataItem objectForKey:#"Title"];
building.subtitle = [dataItem objectForKey:#"Subtitle"];
MKCoordinateRegion buildingcoordinates = { {0.0, 0.0}, {0.0, 0.0} };
buildingcoordinates.center.latitude = [[dataItem objectForKey:#"Latitude"] floatValue];
buildingcoordinates.center.longitude = [[dataItem objectForKey:#"Longitude"] floatValue];
building.coordinate = buildingcoordinates.center;
[self.mapView addAnnotation:building];
}
[super viewDidLoad];
}
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString *pinIdentifier = #"pinIndentifier";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)
[self.mapView dequeueReusableAnnotationViewWithIdentifier:pinIdentifier];
if (pinView == nil)
{
// if an existing pin view was not available, create one
MKPinAnnotationView *customPinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:pinIdentifier];
customPinView.pinColor = MKPinAnnotationColorPurple;
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
Annotation.h:
#import <Foundation/Foundation.h>
#import <MapKit/MKAnnotation.h>
#interface Annotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property(nonatomic, assign) CLLocationCoordinate2D coordinate;
#property(nonatomic, copy) NSString *title;
#property(nonatomic, copy) NSString *subtitle;
#end
Annotation.m:
#import "Annotation.h"
#implementation Annotation
#synthesize coordinate, title, subtitle;
#end
Most likely the map view's delegate is not set which means the viewForAnnotation delegate method will not get called.
Since you've declared mapView as an IBOutlet, in the xib, make sure that the map view's delegate is connected to File's Owner.
Alternatively, at the top of the viewDidLoad method in MapViewController, set it programmatically:
mapView.delegate = self;