0
votes

Progressing apace, trying to learn in and outs of MapKit and annotations.

I've made some good progress, but I'm having problems when I attempt to add location services to the mix.

If I return nil to the

     - (MKAnnotationView *)mapView:(MKMapView *)mapView 
                 viewForAnnotation:(id < MKAnnotation >)annotation

method, I get a result VERY close to what I'm looking for, I have my annotation pins, I have my user's location showing in a standard way.

But if I return myPins (with all the parameters set as below), I get the correct behavior on all the pins but the properties are also set for the user's location (it's a red pin, it drops into place every time the view moves or a pin is selected). Annoying.

How does one set the properties for the annotations separately from the location? Is there a way to return multiple MKAnnotationViews? I know I'm missing some basic concept, but would appreciate any help you can give me. Thanks in advance.

Here's my main viewController, in total:

//
//  ViewController.m
//  mapFun
//


#import "ViewController.h"

@implementation ViewController
@synthesize segmentedControl;
@synthesize mapView,location, myLocations, myAnnotation, region;

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}

- (void)viewDidLoad
{
[super viewDidLoad];

self.mapView.delegate = self; 

//location manager stuff

CLLocationManager *locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];

if([CLLocationManager locationServicesEnabled])
{
[self.mapView setShowsUserLocation:YES];
[locationManager startUpdatingHeading]; 
}

[self loadUpLocations];

//set first zoom center and span, to zoom from to initial zoom

region.center=CLLocationCoordinate2DMake(
                                         33.75070416856952, 
                                         -84.37034368515015);
MKCoordinateSpan span;
span.latitudeDelta=.3;
span.longitudeDelta=.3;
region.span=span;

[mapView setRegion:region animated:YES];

}

- (void)viewDidUnload
{
[self setMapView:nil];
[self setSegmentedControl:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}

- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];

//zoom to initial zoom
 [self setInitialZoom];
}

- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

//Load up a buncha locations

-(void)loadUpLocations{

myLocations =  [LoadObjectsFromFile loadFromFile:@"locations2" ofType:@"plist"];

//loop through and make annotations

for (NSString *loc in myLocations) {
    NSDictionary *value =[myLocations objectForKey:loc];

    //create instance of MapAnnotations
    CLLocationCoordinate2D temp = 
    CLLocationCoordinate2DMake(
                               [[value objectForKey:@"latitude"] doubleValue],
                               [[value objectForKey:@"longitude"] doubleValue]);

    myAnnotation = [[MapAnnotations alloc]initWithLocation:temp];
    myAnnotation.title = [value objectForKey:@"title"];
    myAnnotation.subtitle = [value objectForKey:@"subtitle"];
    myAnnotation.info =[value objectForKey:@"info"];

    [self.mapView addAnnotation:myAnnotation];

}
}

- (void)setInitialZoom{

// MKCoordinateRegion region;
region.center = CLLocationCoordinate2DMake(33.77, -84.37);

//set level of zoom
MKCoordinateSpan span;
span.latitudeDelta=.04;
span.longitudeDelta=.04;
region.span=span;
[mapView setRegion:region animated:YES];
}

// used when selecting annotations

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{

MKPointAnnotation *selectedAnnotation = view.annotation;

NSLog(@"The annotation selected is %@.",selectedAnnotation.title);

//set level of zoom
CLLocationCoordinate2D newCenter = 
CLLocationCoordinate2DMake(
                           selectedAnnotation.coordinate.latitude,
                           selectedAnnotation.coordinate.longitude);
MKCoordinateSpan span;
span.latitudeDelta=.02;
span.longitudeDelta=.02;
MKCoordinateRegion zoomRegion = MKCoordinateRegionMake(newCenter, span);

[ self.mapView setRegion:zoomRegion animated:YES];

}

- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
// [self zoomOutToInitial:nil];
}

- (IBAction)zoomOutToInitial:(id)sender {

[self.mapView setRegion:region animated:YES];
}

- (IBAction)segChanged:(id)sender {
if (self.segmentedControl.selectedSegmentIndex==0) {
    [self.mapView setMapType:MKMapTypeStandard];
}
if (self.segmentedControl.selectedSegmentIndex==1) {
    [self.mapView setMapType:MKMapTypeSatellite];
}
if (self.segmentedControl.selectedSegmentIndex==2) {
    [self.mapView setMapType:MKMapTypeHybrid];
}
}

// This gets called every time an annotation is in the map view

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id < MKAnnotation >)annotation
{
NSLog(@"Map view can see annotation %@.",annotation.title);
MKPinAnnotationView *myPins;
if (!myPins) {
    myPins= [[MKPinAnnotationView alloc]initWithAnnotation:self.myAnnotation 
                                  reuseIdentifier:@"myPins"];
}

myPins.animatesDrop = YES;
myPins.canShowCallout = YES;
myPins.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

return nil;
//return myPins;
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[manager stopUpdatingHeading];
}
@end

Answering my own question. Thanks anyway.

I finally found the answer in a useful document called "Location Awareness Programming Guide," from Apple.

Here's the corrected MKAnnotationView method:

// This gets called every time an annotation is in the map view

- (MKAnnotationView *)mapView:(MKMapView *)theView 
            viewForAnnotation:(id < MKAnnotation >)annotation
{
    NSLog(@"Map view can see annotation %@.",annotation.title);

   //if the annotation is a user location
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        return nil;
    }

//uses my custom class

if ([annotation isKindOfClass:[MapAnnotations class]]) {

    // try for reuse of pins

    MKPinAnnotationView *myPins = (MKPinAnnotationView *) 
              [theView dequeueReusableAnnotationViewWithIdentifier:@"myPins"];

    if (!myPins) {

            myPins= [[MKPinAnnotationView alloc]initWithAnnotation:annotation 
                                                   reuseIdentifier:@"myPins"];
            myPins.animatesDrop = YES;
            myPins.canShowCallout = YES;
            myPins.rightCalloutAccessoryView = 
            [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

        }else
            myPins.annotation = annotation;
        return myPins;
    }
    return nil;
}
1

1 Answers

1
votes

The basic concept is to return if and only if the view asked is actually the userlocation view. You simply test if the Annotation forwarded to you is of userlocation class, like this:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id < MKAnnotation >)annotation
{
  if ([annotation isKindOfClass:[MKUserLocation class]])
        return nil;
// do your usual stuff
}