Get variable and plug it into MKAnnotationView - iphone

I have code which i gives coordinates, title, subtitle, image file location information. This information is used to generate the annotation for a ios mapkit pin. The title and subtitle are automatically plugged in and i can grab the other info (image file location) after the pin is selected. I am looking to display a thumbnail of the image in the annotation (pin popup) however but i am having trouble setting it as a variable to get it from my info as opposed to hard coding it. Below is the code i use to generate my map/ pins.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
// Boilerplate pin annotation code
UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
NSString *imageLoc;
MKPinAnnotationView *pin = (MKPinAnnotationView *) [self.map dequeueReusableAnnotationViewWithIdentifier: #"restMap"];
if (pin == nil) {
pin = [[[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: #"restMap"] autorelease];
} else {
pin.annotation = annotation;
}
pin.pinColor = MKPinAnnotationColorRed;
pin.canShowCallout = YES;
pin.animatesDrop = YES;
NSString *imageLoc= ????????????
UIImageView *leftIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageLoc]];
pin.leftCalloutAccessoryView = leftIconView;
[detailButton addTarget:self action:#selector(showDetailView:) forControlEvents:UIControlEventTouchUpInside];
pin.rightCalloutAccessoryView = detailButton;
return pin;
}
#interface MapPin : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *subtitle;
NSString *title;
NSString *indexnumber;
NSString *imageFile;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, readonly) NSString *title;
#property (nonatomic, readonly) NSString *subtitle;
#property (nonatomic, readonly) NSString *indexnumber;
#property (nonatomic, readonly) NSString *imageFile;
-(id)initWithCoordinates:(CLLocationCoordinate2D)location
placeName: placeName
description:description
indexnum:indexnum
imageFileLoc:imageFileLoc;
#end
#import "MapPin.h"
#implementation MapPin
#synthesize coordinate;
#synthesize title;
#synthesize subtitle;
#synthesize indexnumber;
#synthesize imageFile;
-(id)initWithCoordinates:(CLLocationCoordinate2D)location
placeName: placeName
description:description
indexnum:indexnum
imageFileLoc:imageFileLoc{
self = [super init];
if (self != nil) {
imageFile=imageFileLoc;
[imageFile retain];
indexnumber=indexnum;
[indexnumber retain];
coordinate = location;
title = placeName;
[title retain];
subtitle = description;
[subtitle retain];
}
return self;
}

What's available from the annotation object? Have you tried the following?
NSString *imageLoc = [annotation respondsToSelector:#selector(imageFile)] ? [annotation imageFile] : #"some_default_value";

Related

did select annotation for multiple markers

I am adding multiple markers in the map view like this,
markers = [jsonDict objectForKey:key];
for (id k in markers) {
if ([k isEqualToString:#"latitude"]) {
mlat = [markers objectForKey:k];
dlat = [mlat doubleValue];
}
else if ([k isEqualToString:#"longitude"]) {
mlng = [markers objectForKey:k];
dlng = [mlng doubleValue];
}
else if ([k isEqualToString:#"file"]){
murl = [markers objectForKey:k];
}
else if ([k isEqualToString:#"comment"]){
mcomment = [markers objectForKey:k];
}
}
annotationCoord.latitude = dlat;
annotationCoord.longitude = dlng;
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
annotationPoint.coordinate = annotationCoord;
[self.navimap addAnnotation:annotationPoint];
now, i would like to get the value of "comment" and "file" for each marker in the didSelectAnnotationView. it would be grateful if anybody helps me in this.
You should create a custom annotation class and use it rather than MKPointAnnotation:
#import <MapKit/MapKit.h>
#interface Marker : NSObject <MKAnnotation>
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic) CLLocationCoordinate2D coordinate;
#property (nonatomic,copy) NSString* url;
#property (nonatomic,copy) NSString* comment;
#end
You would then implement didSelectAnnotationView like this:
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
if ([view.annotation isKindOfClass:[Marker class]]) {
Marker* marker = view.annotation;
NSLog(#"selected marker %#", marker);
}
}

How to extend MKPointAnnotation and add a property to it

I'm trying to extend MKPointAnnotation and add a property to for an NSString called dealLink.
I thought I set it up correctly, but I'm getting this error at the moment:
Property 'dealLink' not found on object of type 'MKPointAnnotation *'
Here's my code in a view controller called MapOffersViewController.m:
#pragma mark - Populate Map
- (void)populateMap:(MKMapView*)map withDeals:(NSArray*) deals
{
NSLog(#"Deals " );
for (NSDictionary *currentDeal in deals) {
CLLocationCoordinate2D ctrpoint;
ctrpoint.latitude = [[[currentDeal objectForKey:#"coords"] objectForKey:#"lat"] doubleValue];
ctrpoint.longitude =[[[currentDeal objectForKey:#"coords"] objectForKey:#"lng"] doubleValue];
MKPointAnnotation *dealAnnotation = [[MKPointAnnotation alloc] init];
dealAnnotation.coordinate = ctrpoint;
dealAnnotation.title = [currentDeal objectForKey:#"vendor"];
**dealAnnotation.dealLink = [currentDeal objectForKey:#"link"];**
NSDictionary *currDict = #{
#"EUR": #"€",
#"GBP": #"₤",
#"USD": #"$",
#"BRL": #"R$"
};
NSString *currName = [currentDeal objectForKey:#"currency"];
NSString *currency = [currDict objectForKey:currName];
dealAnnotation.subtitle = [NSString stringWithFormat:#"%#%i",currency,[[currentDeal objectForKey:#"price"] integerValue ]];
NSLog(#"current deal id is %#",[currentDeal objectForKey:#"id"]);
[map setDelegate:self];
[map addAnnotation:dealAnnotation];
}
}
I'm importing this class called MapAnnotation.h:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MapAnnotation : MKPointAnnotation
{
NSString *title;
NSString *subtitle;
NSString *dealLink;
CLLocationCoordinate2D coordinate;
}
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, retain) NSString *dealLink;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithTitle:(NSString *)ttl subTitle:(NSString *)subttl dealLink:(NSString *)dealLnk andCoordinate:(CLLocationCoordinate2D)c2d;
#end
and it's .m:
#import "MapAnnotation.h"
#implementation MapAnnotation
#synthesize title,subtitle,dealLink,coordinate;
- (id)initWithTitle:(NSString *)ttl subTitle:(NSString *)subttl dealLink:(NSString *)dealLnk andCoordinate:(CLLocationCoordinate2D)c2d {
title = ttl;
subtitle = subttl;
dealLink = dealLnk;
coordinate = c2d;
return self;
}
#end
thanks for any help
I used Craig's answer below and this additional code to get this working:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
NSLog(#"callout tapped from del method %#", dealUrl);
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:dealUrl]];
}
- (void)mapView:(MKMapView *)mapView1 didSelectAnnotationView:(MKAnnotationView *)mapView2
{
MapAnnotation *annotation = mapView2.annotation;
NSString *temp = annotation.dealLink;
dealUrl = temp;
// NSLog(#"temp is %#", temp);
}
You're creating an MKPointAnnotation and trying to access dealLink, which is only on MapAnnotations. You need to create a MapAnnotation
....
ctrpoint.longitude =[[[currentDeal objectForKey:#"coords"] objectForKey:#"lng"] doubleValue];
MapAnnotation *dealAnnotation = [[MapAnnotation alloc] init];
dealAnnotation.coordinate = ctrpoint;
....

'MyAnnotation' may not respond to 'initWithDictionary:'

I keep getting this semantic issue with this code ('MyAnnotation' may not respond to 'initWithDictionary:'), im adding annotations to a map using a plist.
Even though it displays the pin and everything i want it to, i get an semantic issue and cant seem to solve the problem
if anyone could help that would be great thanks
heres the code, the problem is in the //BrewMapViewController.m the error is on this line
MyAnnotation *annotation = [[MyAnnotation alloc] initWithDictionary:breweryDict];
/*MyAnnotation.h*/
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
NSString *test;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, copy) NSString *test;
#end
/*MyAnnotation.m*/
#import "MyAnnotation.h"
#implementation MyAnnotation
#synthesize coordinate, title, subtitle, test;
- (id) initWithDictionary:(NSDictionary *) dict
{
self = [super init];
if (self != nil) {
coordinate.latitude = [[dict objectForKey:#"latitude"] doubleValue];
coordinate.longitude = [[dict objectForKey:#"longitude"] doubleValue];
self.title = [dict objectForKey:#"name"];
self.subtitle = [dict objectForKey:#"address"];
self.test = [dict objectForKey:#"test"];
}
return self;
}
#end
/*BrewMapViewController.h*/
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface BrewMapViewController : UIViewController <MKMapViewDelegate> {
IBOutlet MKMapView *map;
NSArray *breweries;
}
#end
/*BrewMapViewController.m*/
#import "BrewMapViewController.h"
#import "MyAnnotation.h"
#implementation BrewMapViewController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
breweries = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:#"test"
ofType:#"xml"]];
double minLat = [[breweries valueForKeyPath:#"#min.latitude"] doubleValue];
double maxLat = [[breweries valueForKeyPath:#"#max.latitude"] doubleValue];
double minLon = [[breweries valueForKeyPath:#"#min.longitude"] doubleValue];
double maxLon = [[breweries valueForKeyPath:#"#max.longitude"] doubleValue];
MKCoordinateRegion region;
region.center.latitude = (maxLat + minLat) / 2.0;
region.center.longitude = (maxLon + minLon) / 2.0;
region.span.latitudeDelta = (maxLat - minLat) * 1.05;
region.span.longitudeDelta = (maxLon - minLon) * 1.05;
map.region = region;
for (NSDictionary *breweryDict in breweries){
MyAnnotation *annotation = [[MyAnnotation alloc] initWithDictionary:breweryDict];
[map addAnnotation:annotation];
[annotation release];
}
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if (map.userLocation == annotation){
return nil;
}
NSString *identifier = #"MY_IDENTIFIER";
MKAnnotationView *annotationView = [map dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil){
annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:identifier]
autorelease];
annotationView.image = [UIImage imageNamed:#"beer.png"];
annotationView.canShowCallout = YES;
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.leftCalloutAccessoryView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"pretzel.png"]] autorelease];
}
return annotationView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"I've been tapped");
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (void)dealloc {
[breweries release];
[map release];
[super dealloc];
}
#end
You have to put the method signature for - (id) initWithDictionary:(NSDictionary *) dict into your header file in order to tell BrewMapViewController that the method exists:
/*MyAnnotation.h*/
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
NSString *test;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, copy) NSString *test;
- (id) initWithDictionary:(NSDictionary *) dict;
#end

How to display route beteen two latitude and longitude with custom name?

I have implemented one dating application in which I have open iPhone map application with source and destination latitude and longitude.But when i touch on the drop pin it display unkown road.But I want to display like user1 and user2 on drop pin.
Please help me for this query
Thanks in advance.
In your View Controller in which you're implementing MapView, you must be implementing MapView's delegate method, viewForAnnotation!!!
Implement it like this:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
MKAnnotationView * annotationView = nil;
[mapLoadingIndicatorView stopAnimating];
if ([annotation isKindOfClass:[MKUserLocation class]]) {
[self.mapView.userLocation setTitle:#"User1"];
return annotationView;
}
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentAnnotation"];
annotationView.canShowCallout = YES;
return annotationView;
}
And also make sure you've made an AddressAnnotation Class in which
AddressAnnotation.h
#interface AddressAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString * title_;
NSString * subtitle_;
}
#property (nonatomic, readwrite, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, retain) NSString * title_;
#property (nonatomic, retain) NSString * subtitle_;
#end
And AddressAnnotation.m:
#implementation AddressAnnotation
#synthesize coordinate, title_, subtitle_;
- (id)initWithCoordinate:(CLLocationCoordinate2D)c: (NSString *)title: (NSString *)subtitle {
if ((self = [super init])) {
coordinate= c ;
self.title_ = [NSString stringWithFormat:#"%#", title];
self.subtitle_ = [NSString stringWithFormat:#"%#", subtitle];
NSLog(#"title_%#", self.title_);
NSLog(#"subtitle_%#", self.subtitle_);
//self.title_ = #"Title";
//self.subtitle_ = #"Subtitle";
}
return self;
}
- (NSString *)title {
return self.title_;
}
- (NSString *)subtitle {
return self.subtitle_;
}
#end

How to show multiple pin annotation in map?

I m showing a pin annotation statically, but i want to do it dynamically to show a lot of pins on map with title and subtitle.
Thx in advance.
I have an array of dictionaries with have two objects lat, long and i am doing this -
if ([resultArray count])
{
for (int i =0; i < [resultArray count]; i++)
{
NSDictionary *dict = [resultArray objectAtIndex:i];
MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
region.center.latitude = [[dict objectForKey:#"lat"] floatValue];
region.center.longitude = [[dict objectForKey:#"long"] floatValue];
region.span.longitudeDelta = 70.0f;
region.span.latitudeDelta = 70.0f;
MyAnnotations *ann = [[MyAnnotations alloc] init];
ann.title = #"title";
ann.coordinate = region.center;
[mapView addAnnotation:ann];
}
}
//
// MyAnnotation.h
//
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
//
// MyAnnotation.m
//
#import "MyAnnotation.h"
#implementation MyAnnotation
#synthesize coordinate,title,subtitle;
-(void)dealloc
{
[title release];
[subtitle release];
[super dealloc];
}
#end
use this delegate for callout -
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id )annotation
{
MKPinAnnotationView *pinView = nil;
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
pinView.pinColor = MKPinAnnotationColorPurple;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[infoButton addTarget:self action:#selector(infoButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = infoButton;
[defaultPinID release];
return pinView;
}