rightCalloutAccessoryView on MKMapView not show - iphone

I have little problem with my iphone application. I have such classes and interfaces:
CinemaMapAnnotation.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface CinemaMapAnnotation : NSObject <MKAnnotation>{
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString* title;
#property (nonatomic, copy) NSString* subtitle;
-(id)initWithCoordinate:(CLLocationCoordinate2D) c;
#end
CinemaMapAnnotation.m
#import "CinemaMapAnnotation.h"
#implementation CinemaMapAnnotation
#synthesize title, subtitle, coordinate;
-(id)initWithCoordinate:(CLLocationCoordinate2D) c{
self = [super init];
if (self) {
coordinate = c;
}
return self;
}
-(void) dealloc {
self.title = nil;
self.subtitle = nil;
[super dealloc];
}
#end
CinemasMapController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "Cinema.h"
#import "CinemaMapAnnotation.h"
#import "PopcornuaAppDelegate.h"
#interface CinemasMapController : UIViewController <MKMapViewDelegate, MKReverseGeocoderDelegate> {
MKMapView *mapView;
MKReverseGeocoder *reverseGeokoder;
}
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
#property (nonatomic, retain) IBOutlet MKReverseGeocoder *reverseGeokoder;
#end
CinemasMapController.m
#import "CinemasMapController.h"
#implementation CinemasMapController
#synthesize mapView, reverseGeokoder;
...
#pragma mark - Map Anotation
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id)annotation
{
static NSString* MyIdentifier = #"CinemaMapAnotation";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:MyIdentifier];
if (!pinView)
{
MKPinAnnotationView* pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:MyIdentifier] autorelease];
pinView.draggable = NO;
pinView.animatesDrop = NO;
pinView.enabled = YES;
} else {
pinView.annotation = annotation;
}
if(annotation != mapView.userLocation){
pinView.pinColor = MKPinAnnotationColorRed;
pinView.canShowCallout = YES;
// Add a detail disclosure button to the callout.
pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.userInteractionEnabled = YES;
} else {
pinView.pinColor = MKPinAnnotationColorGreen;
}
return pinView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
NSLog(#"Not show button, so not work");
}
...
#end
My problem is, what all show and work, except not show rightCalloutAccessoryView button. mapView connected and have delegete to CinemasMapController on iphone view (also I try [mapView setDelegate:self]). So what I do wrong?
P.S. Code with line
pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
execute - checked by NSLog.
Here how its look like - no button:

In viewForAnnotation, in the if (!pinView) block, a new local pinView variable is being declared instead of getting assigned to the outer variable.
As a result, the outer pinView variable never gets set (stays nil) and so the map view creates the default annotation view which is what you see.

Related

Adding custom AnnotationView in iphone

I am using following code to make custom AnnotationView.
My CustomPointAnnotation is a subclass of MKPointAnnotation with a setter/getter of Player
-(void) showMarkers
{
[self.mapView removeAnnotations:[self.mapView annotations]];
for (int i = 0 ; i < [self.playersArray count]; i ++)
{
Players *player = [self.playersArray objectAtIndex:i];
CustomPointAnnotation *annotationPoint = [[CustomPointAnnotation alloc] init];
[annotationPoint setPlayer:player];
if ([player.name isEqualToString:self.name.text])
{
NSLog(#"%# , %#" , player.name,self.name.text);
annotationPoint.coordinate = CLLocationCoordinate2DMake([player.latitude doubleValue]+.1, [player.longitude doubleValue]+.1);
[self.mapView addAnnotation:annotationPoint];
}
else
{
NSLog(#"%# , %#" , player.name,self.name.text);
annotationPoint.coordinate = CLLocationCoordinate2DMake([player.latitude doubleValue], [player.longitude doubleValue]);
[self.mapView addAnnotation:annotationPoint];
}
}
[self.mapView setUserInteractionEnabled:YES];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
// self.mapView.centerCoordinate = userLocation.location.coordinate;
myLocation = userLocation;
}
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if ([[annotation title] isEqualToString:#"Current Location"] )
{
return nil;
}
CustomAnnotationView *annView = [[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"players"];
CustomPointAnnotation *ptAnnotation = (CustomPointAnnotation *) annotation;
[annView setPlayer:ptAnnotation.player];
annView.image = [UIImage imageNamed:#"marker.png"];
annView.enabled = YES;
[annView setUserInteractionEnabled:YES];
return annView;
}
The problem comes at [annView setPlayer:ptAnnotation.player]; Unrecognized selector sent to instance
I am adding CustomPointAnnotation so it should convert it back. How can i solve this issue
OK, Im not sure how you declared the custom class, but it goes like this:
.h:
#interface CustomPointAnnotation: NSObject <MKAnnotation> {
}
#property (nonatomic) CLLocationCoordinate coordinate;
// Other properties like title, subtitle, etc.
.m
#implementation CustomPointAnnotation
#synthesize coordinate; // and other properties
#interface CustomPointAnnotation : NSObject <MKAnnotation&gt
{
Player *player;
}
#property(nonatomic,retain) Player *player;
#property (nonatomic) CLLocationCoordinate coordinate;
Do not subclass MKAnnotation istead confirm to MKAnnotation protocal.
#interface CustomAnnotationView : MKAnnotationView
{
}
no need to set the player. when you need to access the player object access it using the annotation in CustomAnnotationView.
CustomPointAnnotation *annotation=self.annotation;
annotation.player;

XCode Weather Radar Map Overlay on Mapkit

I cant seem to figure this out with loading a custom map overlay from a url. As you can see its load the weather overlay from a URL that adds it to the mapview but it doesnt seem to be working and I cant see why it isnt working. Any help is appreciated.
radarView.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface radarViewController : UIViewController <MKMapViewDelegate> {
MKMapView *mapview;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, readwrite) MKCoordinateRegion region;
#property (nonatomic, readonly) MKMapRect visibleRect;
#property (nonatomic, retain) IBOutlet MKMapView *mapview;
-(IBAction)setMap:(id)sender;
-(IBAction)goBack;
#end
radarView.m
#import "radarViewController.h"
#import "MapOverlay.h"
#import "MapOverlayView.h"
#implementation radarViewController
#synthesize mapview,coordinate,visibleRect,region;
- (void)viewDidLoad
{
[super viewDidLoad];
[mapview setDelegate:self];
[mapview setZoomEnabled:YES];
[mapview setScrollEnabled:YES];
[mapview setMapType:MKMapTypeSatellite];
NSURL *imageURL = [NSURL URLWithString: #"http://radar.weather.gov/ridge/Conus/RadarImg/latest_radaronly.gif"];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
//UIImage * image = [UIImage imageWithData:imageData];
MapOverlay *overlay = [[MapOverlay alloc] initWithImageData:imageData withLowerLeftCoordinate:CLLocationCoordinate2DMake(21.65253888888889, -129.314525) withUpperRightCoordinate:CLLocationCoordinate2DMake(50.406625, -65.60158888888888)];
[mapview addOverlay:overlay];
[mapview setVisibleMapRect:[overlay boundingMapRect]];
[overlay release];
visibleRect = [mapview mapRectThatFits:overlay.boundingMapRect];
mapview.visibleMapRect = visibleRect;
region = MKCoordinateRegionForMapRect(visibleRect);
region.center.latitude = 26.503292;
region.center.longitude = -82.032353;
region.span.longitudeDelta = 0.4f;
region.span.latitudeDelta = 0.4f;
[mapview regionThatFits:region];
[mapview setRegion:region animated:YES];
[mapview setClipsToBounds:true];
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
MapOverlay *mapOverlay = overlay;
MapOverlayView *mapOverlayView = [[[MapOverlayView alloc] initWithOverlay:mapOverlay] autorelease];
return mapOverlayView;
}
#end
MapOverlay.h and .m
#import <MapKit/MapKit.h>
#interface MapOverlay : NSObject <MKOverlay> {
MKMapRect boundingMapRect;
}
#property (nonatomic, retain) NSData *radarData;
- (id) initWithImageData: (NSData*) imageData withLowerLeftCoordinate:
(CLLocationCoordinate2D) lowerLeftCoordinate withUpperRightCoordinate:
(CLLocationCoordinate2D) upperRightCoordinate;
#end
#import "MapOverlay.h"
#implementation MapOverlay
#synthesize radarData,coordinate,boundingMapRect;
- (id) initWithImageData: (NSData*) imageData withLowerLeftCoordinate: (CLLocationCoordinate2D) lowerLeftCoordinate withUpperRightCoordinate: (CLLocationCoordinate2D) upperRightCoordinate{
self.radarData = imageData;
MKMapPoint lowerLeft = MKMapPointForCoordinate(lowerLeftCoordinate);
MKMapPoint upperRight = MKMapPointForCoordinate(upperRightCoordinate);
boundingMapRect = MKMapRectMake(lowerLeft.x, upperRight.y, upperRight.x - lowerLeft.x, upperRight.y - lowerLeft.y);
return self;
}
- (CLLocationCoordinate2D)coordinate
{
return MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMidX(boundingMapRect),
MKMapRectGetMidY(boundingMapRect)));
}
- (MKMapRect)boundingMapRect
{
return boundingMapRect;
}
#end
MapOverlayView.h and .m
#import <MapKit/MapKit.h>
#interface MapOverlayView : MKOverlayView {
CGFloat tileAlpha;
}
#property (nonatomic, assign) CGFloat tileAlpha;
#end
#import "MapOverlayView.h"
#import "MapOverlay.h"
#implementation MapOverlayView
#synthesize tileAlpha;
- (id)initWithOverlay:(id <MKOverlay>)overlay
{
if (self = [super initWithOverlay:overlay]) {
self.tileAlpha = 0.8;
}
return self;
}
- (void)drawMapRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale
inContext:(CGContextRef)context
{
MapOverlay *mapOverlay = (MapOverlay *)self.overlay;
CGContextSetAlpha(context, tileAlpha);
UIImage *image = [[UIImage alloc] initWithData:mapOverlay.radarData];
NSString *strData = [[NSString alloc]initWithData:mapOverlay.radarData encoding:NSUTF8StringEncoding];
NSLog(#"%#",strData);
MKMapRect theMapRect = [self.overlay boundingMapRect];
CGRect theRect = [self rectForMapRect:theMapRect];
UIGraphicsPushContext(context);
[image drawInRect:theRect blendMode:kCGBlendModeNormal alpha:1.0];
UIGraphicsPopContext();
[image release];
}
- (BOOL)canDrawMapRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale
{
return YES;
}
#end

Change UIView's background color

I am doing some exercises with delegate, but now I have a problem with a UIView. This is my storyboard
I want to change the color of the UIView with 3 UISliders. The range of UISliders is from 0 to 255.
And this is my code:
ColorField is the UIView custom class
ColorField.h
#import <UIKit/UIKit.h>
#protocol ColorFieldDelegate <NSObject>
-(NSArray *)giveMeColors;
#end
#interface ColorField : UIView
#property (nonatomic , weak) IBOutlet id<ColorFieldDelegate> delegate;
#end
ColorField.m
#import "ColorField.h"
#implementation ColorField
#synthesize delegate = _delegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
NSArray *arrayOfColors = [self.delegate giveMeColors];
int red = [[arrayOfColors objectAtIndex:0] intValue];
int green = [[arrayOfColors objectAtIndex:1] intValue];
int blue = [[arrayOfColors objectAtIndex:2] intValue];
NSLog(#"Red --> %d" ,red);
NSLog(#"Green --> %d" ,green);
NSLog(#"Blue --> %d \n\n" ,blue);
self.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
}
#end
ColorViewController.h
#import <UIKit/UIKit.h>
#import "ColorField.h"
#interface ColorViewController : UIViewController <ColorFieldDelegate>
#property (nonatomic) IBOutlet ColorField *colorField;
#property (weak, nonatomic) IBOutlet UISlider *redSlider;
#property (weak, nonatomic) IBOutlet UISlider *greenSlider;
#property (weak, nonatomic) IBOutlet UISlider *blueSlider;
#end
ColorViewController.m
#import "ColorViewController.h"
#interface ColorViewController ()
#property (nonatomic) double redQuantity;
#property (nonatomic) double greenQuantity;
#property (nonatomic) double blueQuantity;
#end
#implementation ColorViewController
#synthesize colorField = _colorField;
#synthesize redSlider;
#synthesize greenSlider;
#synthesize blueSlider;
#synthesize redQuantity;
#synthesize blueQuantity;
#synthesize greenQuantity;
- (void)viewDidLoad
{
[super viewDidLoad];
[self.colorField setDelegate:self];
[self.colorField setNeedsDisplay];
self.redQuantity = 125.0;
self.blueQuantity = 125.0;
self.greenQuantity = 125.0;
[self.colorField setNeedsDisplay];
// Do any additional setup after loading the view, typically from a nib.
}
-(ColorField *)colorField
{
if (_colorField == nil) {
_colorField = [[ColorField alloc] init];
}
return _colorField;
}
- (void)viewDidUnload
{
[self setColorField:nil];
[self setRedSlider:nil];
[self setGreenSlider:nil];
[self setBlueSlider:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
-(IBAction)changeRedQuantity:(UISlider *)sender
{
//methods of UISliders
self.redQuantity = [sender value];
[self.colorField setNeedsDisplay];
}
-(IBAction)changeBlueQuantity:(UISlider *)sender
{
self.blueQuantity = [sender value];
[self.colorField setNeedsDisplay];
}
-(IBAction)changeGreenQuantity:(UISlider *)sender
{
self.greenQuantity = [sender value];
[self.colorField setNeedsDisplay];
}
-(NSArray *)giveMeColors
{
NSNumber *redNumber = [NSNumber numberWithDouble:self.redQuantity];
NSNumber *greenNumber = [NSNumber numberWithDouble:self.greenQuantity];
NSNumber *blueNumber = [NSNumber numberWithDouble:self.blueQuantity];
NSArray *array = [[NSArray alloc] initWithObjects:redNumber, greenNumber,blueNumber, nil];
return array;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
BUT...this is the result: It show me only RED, GREEN and BLUE colors without gradation, for example: RGB (255,0,75) is THIS
and not THIS:
I don't know with it can't show me gradation...
Thanks!!
Marco Manzoni
You have to divide your slidervalues by 255.0.
[UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:1.0];
colorWithRed only accepts values 0.0-1.0

Controls in a ViewController losing their state after memory warning while off screen

The situation is very similar to that described by this my other question, except that the delegation seems to work fine. I'm providing some more detail about my code. I'm just striping out non-relevant/trivial parts.
ReportScreen.h
#interface ReportScreen : UIViewController <UIImagePickerControllerDelegate, UITextViewDelegate, MBProgressHUDDelegate, SoapDelegate, MapLocationChoiceDelegate>
// ...
#property (nonatomic, retain) MKPointAnnotation *annotation;
#property (nonatomic, retain) IBOutlet UITextView *textView;
#property (nonatomic, retain) IBOutlet UIButton *cameraButton;
#property (nonatomic, retain) IBOutlet UIButton *libraryButton;
#property (nonatomic, retain) IBOutlet UIButton *locationButton;
#property (nonatomic, retain) IBOutlet UIButton *sendButton;
#end
ReportScreen.m
#implementation ReportScreen
#synthesize annotation;
#synthesize textView;
#synthesize cameraButton;
#synthesize libraryButton;
#synthesize locationButton;
#synthesize sendButton;
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Here I used to store the VC's state to a file but it shouldn't be needed now that I'm assigning it as delegate and said delegate seems to still be there even after a memory warning.
}
- (void)viewDidLoad {
[super viewDidLoad];
placeholderText = #"Tell us what's wrong…";
textView.text = placeholderText;
self.annotation = nil;
[self isReadyToSubmit];
hud = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:hud];
hud.delegate = self;
hud.labelText = #"Invio in corso…";
hud.dimBackground = YES;
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Here I used to restore the state of the VC from file but… y'know.
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self isReadyToSubmit];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"goToMap"]) {
MapScreen *vc = (MapScreen *)segue.destinationViewController;
// HERE's the magic
vc.mapLocationChoiceDelegate = self;
// MAGIC ends
if(self.annotation != nil) {
vc.annotations = [[NSMutableArray alloc] init];
[vc.annotations addObject:self.annotation];
}
}
}
- (BOOL)isReadyToSubmit {
if(self.annotation != nil) {
locationButton.highlighted = YES;
}
if(![textView.text isEqualToString:placeholderText] && self.annotation != nil) {
[sendButton setEnabled:YES];
} else {
[sendButton setEnabled:NO];
}
return [sendButton isEnabled];
}
- (void)textViewDidBeginEditing:(UITextView *)theTextView {
if([theTextView.text isEqualToString:placeholderText]) {
theTextView.text = #"";
}
UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(didFinishEditing:)];
[self.navigationItem setRightBarButtonItem:done animated:YES];
}
- (void)textViewDidEndEditing:(UITextView *)theTextView {
if([theTextView.text isEqualToString:#""]) {
theTextView.text = placeholderText;
}
[self isReadyToSubmit];
}
- (void)didFinishEditing:(id)sender {
[self.navigationItem setRightBarButtonItem:nil animated:YES];
[self.textView resignFirstResponder];
}
// THIS is my delegate protocol's method
- (void)locationChosen:(MKPointAnnotation *)theAnnotation {
self.annotation = theAnnotation;
NSLog(#"R: %#", textView.text);
}
#end
MapScreen.h
#protocol MapLocationChoiceDelegate <NSObject>
- (void)locationChosen:(MKPointAnnotation *)annotation;
#end
// ---
#interface MapScreen : UIViewController <MKMapViewDelegate>
- (void)handleLongPress:(id)sender;
#property (nonatomic, retain) NSMutableArray *annotations;
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
#property (weak) id<MapLocationChoiceDelegate> mapLocationChoiceDelegate;
#end
MapScreen.m
#implementation MapScreen
#synthesize annotations;
#synthesize mapView;
#synthesize mapLocationChoiceDelegate;
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidLoad {
[super viewDidLoad];
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
lpgr.minimumPressDuration = 1.0;
[self.mapView addGestureRecognizer:lpgr];
[mapView addAnnotations:self.annotations];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
#pragma mark - Map handling
- (void)handleLongPress:(id)sender {
if(![sender isKindOfClass:[UILongPressGestureRecognizer class]]) {
return;
}
UILongPressGestureRecognizer *gr = (UILongPressGestureRecognizer *)sender;
if (gr.state != UIGestureRecognizerStateBegan) {
return;
}
CGPoint touchPoint = [gr locationInView:self.mapView];
CLLocationCoordinate2D touchMapCoordinate = [self.mapView convertPoint:touchPoint toCoordinateFromView:self.mapView];
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
annotation.coordinate = touchMapCoordinate;
self.annotations = [NSMutableArray arrayWithArray:[mapView annotations]];
for(id a in self.annotations) {
if(![a isKindOfClass:[MKUserLocation class]]) {
[mapView removeAnnotation:a];
}
}
[mapView addAnnotation:annotation];
self.annotations = [NSMutableArray arrayWithArray:[mapView annotations]];
// NSDictionary *userInfo = [NSDictionary dictionaryWithObject:annotation forKey:#"annotation"];
// [[NSNotificationCenter defaultCenter] postNotificationName:#"PositionChosen" object:nil userInfo:userInfo];
[self.mapLocationChoiceDelegate locationChosen:annotation];
NSLog(#"M: %#", ((ReportScreen *)self.mapLocationChoiceDelegate).textView.text);
}
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation {
if([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
static NSString *AnnotationIdentifier = #"Annotation";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)[theMapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView) {
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
} else {
pinView.annotation = annotation;
}
return pinView;
}
#end
The issue is:
ReportScreen pushes (performs segue to, actually) the MapScreen.
If I have some data in the UITextView or if I set some state to the buttons in the ReportScreen and I get a memory warning while the MapScreen is pushed, once I go back to the ReportScreen, all those fields don't show those settings. Apparently textView.text is still set, and so are the states of the buttons, they're just not shown.
Question: why?

custom MKAnnotation class for changing leftCalloutAnnotationView

I have created a custom class for the MKAnnotation
#interface NeighborMapAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString * title;
NSString * subtitle;
UIImageView * lcav;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) NSString * subtitle;
#property (nonatomic, retain) UIImageView * lcav;
#end
NeighborMapAnnotation *neighbor = [[NeighborMapAnnotation alloc] initWithCoordinate:aCoordinate];
//imgView is some UIImageView that I already have
neighbor.leftCalloutAccessoryView = imgView;
- (MKAnnotationView *) mapView:(MKMapView *) mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
MKPinAnnotationView * annView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"custom view"] autorelease];
annView.animatesDrop = YES;
annView.canShowCallout = YES;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annView.rightCalloutAccessoryView = rightButton;
annView.leftCalloutAccessoryView = [annotation lcav];//is this right?
return annView;
}
I want to be able to change the leftCalloutAccessoryView of the annotation to an image. What code should I change in my custom MKAnnotation class?
The leftCalloutAccessoryView property is a property of the MKAnnotationView class (not in the MKAnnotation protocol).
In the viewForAnnotation delegate method of MKMapView, you provide an MKAnnotationView for your annotations. In that method, check if the annotation type is your custom annotation type using isKindOfClass and set the view's properties as needed.
In your NeighborMapAnnotation class, you could store the imageView as a UIImageView property and set that when creating the annotation.
In viewForAnnotation, you would set the view's leftCalloutAccessoryView to the annotation's imageView.
Edit:
Here's one way to implement it...
Add an image property to your custom annotation class:
#interface NeighborMapAnnotation : NSObject <MKAnnotation> {
...
UIImage *image;
}
...
#property (nonatomic, retain) UIImage *image;
#end
At the place where you create your annotations, set the image property:
NeighborMapAnnotation *neighbor = [[NeighborMapAnnotation alloc] initWithCoordinate:aCoordinate];
neighbor.image = [UIImage imageNamed:#"someimage.png"];
//the image could be different for each annotation
...
In the viewForAnnotation delegate method (make sure map view's delegate is set):
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[NeighborMapAnnotation class]])
{
static NSString *AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView)
{
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
}
else
{
pinView.annotation = annotation;
}
UIImageView *leftCalloutView = [[UIImageView alloc]
initWithImage:((NeighborMapAnnotation *)annotation).image];
pinView.leftCalloutAccessoryView = leftCalloutView;
[leftCalloutView release];
return pinView;
}
return nil;
}
thats great! i tried to extend my custom annotation class by few properties. but i had no access inside of viewForAnnotation delegate. what i´ve missed and learned here is that i have to cast the additional property on my custom annotation class. now it works! thank you! :-)