Reputation: 864
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;
}
Upvotes: 0
Views: 2584
Reputation: 1400
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
}
Upvotes: 1