0
votes

I have a map view with several annotations. Each annotation has a button that takes the user to a detail view for that annotation. The detail view currently has two labels, one for the title from the annotation and the other for the subtitle of the annotation, and a "Get Directions" button. I want the title label to be populated with the title from the annotation and the subtitle label to be populated with the subtitle from the annotation. I want the Get Directions button to take the user into the Maps app and give them directions to the address from their current location. I'd also like to add website and phone number to the detail view but I'm not sure how to populate those fields either. The detail view is called AnnotationDetailView but I haven't done anything with it besides add the button and labels in IB. I'm just not sure how to populate the labels and get the button doing what I want. Any help would be great.

Here is my code:

//
//  RSFM.m

#import "RSFM.h"
#import "AnnotationDetailView.h"

@interface RSFM ()

@end

@implementation RSFM
{

}

@synthesize centerCoordinate, coordinate, title, subtitle;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if (self)
    {
        self.title = NSLocalizedString(@"Farm Markets", @"Farm Markets");
        // Create location manager object
        locationManager = [[CLLocationManager alloc]init];

        [locationManager setDelegate:self];

        // And we want it to be as accurate as possible regardless of how much time/power it takes
        [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];

        // Tell our manager to start looking for its location immediately
        // [locationManager startUpdatingLocation];
    }

    return self;
}
/*
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
{
    centerCoordinate = CLLocationCoordinate2DMake(37.7885, 85.3279);
}
*/
- (void)findLocation
{
    [locationManager startUpdatingLocation];
    [activityIndicator startAnimating];
    // [locationTitleField setHidden:YES];
    [locationManager stopUpdatingLocation];
}

- (void)foundLocation:(CLLocation *)loc
{
    CLLocationCoordinate2D coord = [loc coordinate];

    // Create an instance of BNRMapPoint with the current data
    // BNRMapPoint *mp = [[BNRMapPoint alloc]initWithCoordinate:coord title:[locationTitleField text]];
    // Add it to the map view
    // [worldView addAnnotation:mp];

    // Zoom the region to this location
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(coord, 700000, 700000);
    [worldView setRegion:region animated:YES];

    // Reset the UI
    // [locationTitleField setText:@""];
    [activityIndicator stopAnimating];
    // [locationTitleField setHidden:NO];
    [locationManager stopUpdatingLocation];
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    NSLog(@"%@", newLocation);

    // How many seconds ago was this new location created?
    NSTimeInterval t = [[newLocation timestamp]timeIntervalSinceNow];

    // CLLocationManagers will return the last found location of the device first, you don't want that data in this case.
    // If this location was made more than 3 minutes ago, ignore it.
    if (t < -180)
    {
        // this is cached data, you don't want it, keep looking
        return;
    }

    [self foundLocation:newLocation];
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"Could not find location: %@", error);
}

- (void)dealloc
{
    // Tell the location manager to stop sending us messages
    [locationManager setDelegate:nil];
}

- (IBAction)showDetails:(id)sender
{
    AnnotationDetailView *detail = [[AnnotationDetailView alloc] initWithNibName:nil bundle:nil];
    detail.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    [self.navigationController pushViewController:detail animated:YES];
}

- (MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    // If it's the user location, return nil
    if ([annotation isKindOfClass:[MKUserLocation class]])
        return nil;

    // Try to dequeue an existing pin view first
    static NSString *annotationIdentifier = @"AnnotationIdentifier";
    MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
    pinView.animatesDrop = YES;
    pinView.canShowCallout = YES;

    UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    [rightButton setTitle:annotation.title forState:UIControlStateNormal];
    [rightButton addTarget:self action:@selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
    pinView.rightCalloutAccessoryView = rightButton;

    return pinView;
}

- (void)viewDidLoad
{
    [locationManager startUpdatingLocation];
    [worldView setShowsUserLocation:YES];
    [locationManager stopUpdatingLocation];

    NSMutableArray *marketLocations = [[NSMutableArray alloc]init];

    NSMutableArray *lat = [[NSMutableArray alloc]initWithObjects:@"37.7867266", @"37.0703517", @"37.1610806", @"37.318367", @"37.3559204", @"37.4154066", @"37.4757622", @"37.7450252", @"37.6318978", @"37.0716803", nil];

    NSMutableArray *lon = [[NSMutableArray alloc]initWithObjects:@"-87.608209", @"-88.1237899", @"-87.9148629", @"-87.5074402", @"-87.5448032", @"-87.8003148", @"-87.9515986", @"-87.9061638", @"-87.1148574", @"-87.3008418", nil];

    NSMutableArray *title1 = [[NSMutableArray alloc]initWithObjects:@"Cates Farm", @"Broadbent B & B Foods", @"Cayce's Pumpkin Patch", @"Metcalfe Landscaping", @"Brumfield Farm Market", @"Dogwood Valley Farm", @"Country Fresh Meats & Farmers Market", @"Jim David Meats", @"Trunnell's Farm Market", @"Lovell's Orchard & Farm Market", nil];

    NSMutableArray *subtitle1 = [[NSMutableArray alloc]initWithObjects:@"Hwy 425 Henderson, KY 42420", @"257 Mary Blue Road Kuttawa, KY 42055", @"153 Farmersville Road Princeton, KY 42445", @"410 Princeton Road Madisonville, KY 42431", @"3320 Nebo Road Madisonville, KY 42431", @"4551 State Route 109N Clay, KY 42404", @"9355 US Hwy 60 W Sturgis, KY 42459",@"350 T. Frank Wathen Rd. Uniontown, KY 42461", @"9255 Hwy 431 Utica, KY 42376", @"22850 Coal Creek Road Hopkinsville, KY 42240", nil];

    CLLocationCoordinate2D location;
    MKPointAnnotation *marketAnnotation;

    for (int x = 0; x < [lat count]; x++)
    {
        marketAnnotation = [[MKPointAnnotation alloc]init];
        location.latitude = [[lat objectAtIndex:x]floatValue];
        location.longitude = [[lon objectAtIndex:x]floatValue];
        marketAnnotation.coordinate = location;
        marketAnnotation.title = [title1 objectAtIndex:x];
        marketAnnotation.subtitle = [subtitle1 objectAtIndex:x];
        [marketLocations addObject:marketAnnotation];
    }

    [worldView addAnnotations:marketLocations];

    /*
    MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
    point.coordinate = CLLocationCoordinate2DMake(37.7867266, -87.608209);
    point.title = @"Cates Farm";
    point.subtitle = @"Hwy 425 Henderson, KY 42420";
    [worldView addAnnotation:point];
     */
}

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    CLLocationCoordinate2D loc = [userLocation coordinate];
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(loc, 700000, 700000);
    [worldView setRegion:region animated:YES];
    [locationManager stopUpdatingLocation];
    locationManager.delegate = nil;
}

- (IBAction)selectSegmentControl
{
    int segmentTouched = [mapVarieties selectedSegmentIndex];
    NSString *segmentName = [mapVarieties titleForSegmentAtIndex:segmentTouched];
    if ([segmentName isEqualToString:@"Street"])
    {
        [worldView setMapType:MKMapTypeStandard];
    }
    if ([segmentName isEqualToString:@"Satellite"])
    {
        [worldView setMapType:MKMapTypeSatellite];
    }
    if ([segmentName isEqualToString:@"Hybrid"])
    {
        [worldView setMapType:MKMapTypeHybrid];
    }
}

@end

Here is where I show the detail view

- (IBAction)showDetails:(id)sender
{
    AnnotationDetailView *detail = [[AnnotationDetailView alloc] initWithNibName:nil bundle:nil];
    detail.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    NSLog(@"%@", marketAnnotation.title);
    detail.ti.text = marketAnnotation.title;
    [self.navigationController pushViewController:detail animated:YES];
}

and the AnnotationDetailView

//
//  AnnotationDetailView.m

#import "AnnotationDetailView.h"

@interface AnnotationDetailView ()

@end

@implementation AnnotationDetailView

@synthesize ti;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    // [title setText:marketAnnotation.title];
    // [subtitle setText:marketAnnotation.subtitle];
    ti = [[UILabel alloc]initWithFrame:CGRectMake(20, 20, 281, 21)];
    [self.view addSubview:ti];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

I'm having a couple of issues with this. One, the label is not showing up. Two, I have an NSLog statement in my showDetails method to show me what marketAnnotations is. It is showing the title of the last annotation added.

1

1 Answers

0
votes

You can add extra parameters to your MKAnnotation class. For example this Annotation class uses 3 extra strings to hold information:

//  MyAnnotation.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface MyAnnotation : NSObject <MKAnnotation>

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy, readonly) NSString *title;
@property (nonatomic, copy, readonly) NSString *subtitle;
@property (nonatomic, copy, readonly) NSString *myString1;
@property (nonatomic, copy, readonly) NSString *myString2;
@property (nonatomic, copy, readonly) NSString *myString3;

-(id)initWithCoordinates:(CLLocationCoordinate2D) paramCoordinates
               title:(NSString *) paramTitle
            subTitle:(NSString *) paramSubTitle
           myString1:(NSString *) paramMyString1
           myString2:(NSString *) paramMyString2
           myString3:(NSString *) paramMyString3;

@end

//  MyAnnotation.m
#import "MyAnnotation.h"

@implementation MyAnnotation

-(id)initWithCoordinates:(CLLocationCoordinate2D)paramCoordinates
               title:(NSString *)paramTitle
            subTitle:(NSString *)paramSubTitle
            myString1:(NSString *)paramMyString1
            myString2:(NSString *)paramMyString2
            myString3:(NSString *)paramMyString1
{
self = [super init];
if(self != nil)
{
    _coordinate = paramCoordinates;
    _title = paramTitle;
    _subtitle = paramSubTitle;
    _myString1 = paramMyString1;
    _myString2 = paramMyString2;
    _myString3 = paramMyString3;

}
return (self);
}

@end

When the user taps a pin, you can do this to pass information from the Annotation to the next View Controller:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
if ([(UIButton*)control buttonType] == UIButtonTypeDetailDisclosure)
{
    YourViewController *vc = [[YourViewController alloc] init];
    [vc setTitleString:[(MyAnnotation *)view.annotation title]];
    [vc setSubTitleString:[(MyAnnotation *)view.annotation subTitle]];
    [vc setPassedString1:[(MyAnnotation *)view.annotation myString1]];
    [vc setPassedString2:[(MyAnnotation *)view.annotation myString2]];
    [vc setPassedString3:[(MyAnnotation *)view.annotation myString3]];
    [[self navigationController] pushViewController:vc animated:YES];
}
}

In your next View Controller (vc), you can modify the button text like this:

[myButton setTitle:myPassedString1 forState:UIControlStateNormal];