I have tried to find an answer online and maybe there is an answer out there but I’m struggling to find it.
The Concept – I have data downloaded from an SQL. I collect this data and an array displays the annotations on the map. When the annotation is clicked the correct title and subtitle are shown. When the button on the annotation is clicked a new View pops up display data relevant to that co-ordinate.
The Problem – In this data that I download from an SQL there is other data apart from title, co-ordinates etc that I want passed to this other view, such as images, details, price, website details etc. I can do this without problems through a table view (the index:row method), but for the life of me, not in a Map View.
So my question is – how can I collect the information that the annotations pick up and pass this through to the other view along with the other data. I tried adding the extra data in an array with the annotations and produce this when the user clicks the button, but only the last object shows in the array.
I know there is some serious learning I need to get my head around for arrays and passing data about; but any help will be much appreciated.
My Hotspot class:
@interface Hotspot : NSObject <MKAnnotation>
{
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subTitle;
NSString *detail;
float price;
NSString *contact;
}
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subTitle;
@property (nonatomic, copy) NSString *detail;
@property (nonatomic) float price;
@property (nonatomic, copy) NSString *contact;
My MapView (Company class holds the data I got from the SQL file – I load all the data up in ViewDidLoad using ‘companys’ and then use an array (this works okay):-
- (void)loadAnnotations {
NSMutableArray *annotations = [[NSMutableArray alloc] init];
for (int i = 0; i < [companys count]; i++)
// storedNumber = i;
{
Company* company = [self.companys objectAtIndex:i];
CGFloat latitude = company.latitude;
CGFloat longitude = company.longitude;
Hotspot *myAnnotations = [[Hotspot alloc] init];
MKCoordinateRegion region = { { latitude , longitude } , { 12.0f , 12.0f } };
[myAnnotations setCoordinate: region.center];
[myAnnotations setSubTitle:company.type];
[myAnnotations setTitle:company.name];
[myAnnotations setDetail:company.details];
[myAnnotations setPrice:company.price];
[myAnnotations setContact:company.contact];
[annotations addObject: myAnnotations];
}
[promoView addAnnotations: annotations];
My Annotation View (this will need to change once I’ve added your suggestion:
- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation
{
NSLog(@"AnnotationView");
// if it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// static NSString *AnnotationViewID = @"annotationViewID";
MKPinAnnotationView* pinView = (MKPinAnnotationView*)[promoView dequeueReusableAnnotationViewWithIdentifier:@"CustomPinAnnotationView"];
if (!pinView) {
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:@"CustomPinAnnotation"] autorelease];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
NSLog(@"Map View Title, %@", annotation.title);
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self
action:@selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"profile.png"]];
pinView.leftCalloutAccessoryView = profileIconView;
[profileIconView release];
if ([annotation isKindOfClass:[Hotspot class]]) {
pinView.pinColor = MKPinAnnotationColorRed;
pinView.draggable =YES;
}
else
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
}
else
pinView.annotation = annotation;
return pinView;
}
Your code –
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
PromoViewController *promoController = [[PromoViewController alloc] initWithNibName:@"DetailView" bundle:nil];
promoController.hotspot = (Hotspot*)view.annotation;
[self.navigationController pushViewController:promoController animated:YES];
[promoController release];
For the PromoViewController, I’ve set the .h file like this:
@interface PromoViewController : UIViewController
{
IBOutlet UILabel *nameLabel;
IBOutlet UILabel *detailLabel;
IBOutlet UILabel *typeLabel;
IBOutlet UILabel *contactLabel;
IBOutlet UILabel *priceLabel;
}
But I’m not 100% sure how to implement it and also I do get an error with this line:-
promoController.hotspot = (Hotspot*)view.annotation;
Saying that the property hotspot is not found on object PromoViewController.
The type of data that you are passing should have code for them, adhering to the MKAnnotation protocol (namely, title, subtitle and coordinate). Then you pass on that annotation from view to view.
For example (your code would be better), imagine a Hotspot class
In your mapView delegate class, you would do something like this:
Then in your detailViewController, just display the info you want to display: description, title, images etc, as long as they are available in your Hotspot class.
EDIT
After reading your code, you have two choices: add a hotspot property in your PromoViewController or set the labels from the mapView:annotationView:calloutAccessoryControlTapped.
I will go with the first one, which is much better from an encapsulation and design point of view.
Change your PromoViewController header to
And in your PromoViewController.m change the viewWillAppear: method to
You of course need to add @synthesize hotspot at the top of your PromoViewController.m