0

I can zoom the map out to include the user's location and the annotation I want; however I have 2 issues.

  1. I don't want the user's location to have a pin (see image1).
  2. The pins are too close to the edges, and sometimes under the nav/tab bars (see image2). Need some padding but not sure how to accomplish this.

Any help is much appreciated. Below is my code for the map view controller.

#import "BuildingsMapViewController.h"
#import "BuildingsAnnotations.h"

@interface BuildingsMapViewController () 
@end

@implementation BuildingsMapViewController

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

    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    self.locationManager.distanceFilter = kCLDistanceFilterNone;
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [self.locationManager startUpdatingLocation];


    BuildingsAnnotations *userAnnotation = [[BuildingsAnnotations alloc] init];
    userAnnotation.coordinate = self.locationManager.location.coordinate;


    self.mapView.delegate = self;
    self.navigationItem.title = self.title;

    CLLocationCoordinate2D startCenter = CLLocationCoordinate2DMake(42.334596, -83.049578);
    CLLocationDistance regionWidth = 1500;
    CLLocationDistance regionHeight = 1500;

    MKCoordinateRegion startRegion = MKCoordinateRegionMakeWithDistance(startCenter, regionWidth, regionHeight);
    [self.mapView setRegion:startRegion animated:YES];


    self.coordinate = CLLocationCoordinate2DMake(self.geoPoint.latitude,self.geoPoint.longitude);
    BuildingsAnnotations *annotation = [[BuildingsAnnotations alloc] init];
    annotation.coordinate = self.coordinate;
    annotation.title = self.navigationItem.title;
    annotation.subtitle = @"Click for Directions";
    [self.mapView addAnnotation:annotation];
    [self.mapView setCenterCoordinate:annotation.coordinate animated:YES];


    self.annotations = @[annotation, userAnnotation];
    [self.mapView showAnnotations:self.annotations animated:YES];

}

- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations {
    CLLocation *location = [locations lastObject];
    NSLog(@"lat%f - lon%f", location.coordinate.latitude, location.coordinate.longitude);
}

@end

UPDATE: Followed what Duncan said and got it to work. Here's my code:

// Get user coordinates
self.userLat = self.locationManager.location.coordinate.latitude;
self.userLong = self.locationManager.location.coordinate.longitude;

// Initialize and set arrays
self.lats = [[NSMutableArray alloc] init];
self.lngs = [[NSMutableArray alloc] init];

[self.lats addObject:[NSNumber numberWithDouble:self.userLat]];
[self.lats addObject:[NSNumber numberWithDouble:annotation.coordinate.latitude]];
[self.lngs addObject:[NSNumber numberWithDouble:self.userLong]];
[self.lngs addObject:[NSNumber numberWithDouble:annotation.coordinate.longitude]];

// Sort numbers in arrays
[self.lats sortUsingSelector:@selector(compare:)];
[self.lngs sortUsingSelector:@selector(compare:)];

// Get smallest/biggest coordinates
double smallestLat = [self.lats[0] doubleValue];
double smallestLng = [self.lngs[0] doubleValue];
double biggestLat = [[self.lats lastObject] doubleValue];
double biggestLng = [[self.lngs lastObject] doubleValue];

// Get Center Point and Span
CLLocationCoordinate2D annotationsCenter = CLLocationCoordinate2DMake((biggestLat + smallestLat) / 2, (biggestLng + smallestLng) / 2);
MKCoordinateSpan annotationsSpan = MKCoordinateSpanMake((biggestLat - smallestLat) * 1.75, (biggestLng - smallestLng) * 1.75);

// Create and set Region
MKCoordinateRegion region = MKCoordinateRegionMake(annotationsCenter, annotationsSpan);
[self.mapView setRegion:region];
kerbelda
  • 325
  • 1
  • 4
  • 14
  • "I don't want the user's location to have a pin": _Then don't add it as an annotation._ It doesn't look like you need the CLLocationManager in the first place for what you're doing. –  May 22 '14 at 02:47
  • I added it as an annotation because of the showAnnotations: method (saw someone recommend it somewhere). Same with CLLocationManager. At least it shows the 2 locations =/. – kerbelda May 22 '14 at 05:53
  • When showsUserLocation is turned On in the map view, it automatically adds an annotation (the blue dot) for you. However, this may not happen instantly in viewDidLoad. Even with the location manager, the fact that it returns a valid coordinate immediately after you call startUpdatingLocation is serendipitous. The map view will call didUpdateUserLocation when it actually has a coordinate. The showAnnotations or setRegion should be done in didUpdateUserLocation (with some flag to only do that once). –  May 22 '14 at 10:56
  • For the padded region, I recommend [this approach](http://stackoverflow.com/a/7141612/467105) but calling `setVisibleMapRect:edgePadding:animated:` instead of just `setVisibleMapRect:animated:`. –  May 22 '14 at 10:58
  • Several things. If you're getting a pin on top of the user's location, your viewForAnnotation: method needs to be changed to check for the user location and return nil if the current annotation is the user location: `if(annotation == mapView.userLocation) return nil`. – Duncan C May 22 '14 at 21:51
  • Next, why are you creating an array of lats and an array of longs, sorting them, then just adding the two lats and two longs and dividing by 2? Skip all that NSArray mess and simply use `double centerLat = (location.coordinate.latitude+annotation.coordinate.latitude)/2`, and the same approach for longitude. Your code to find the center is needlessly complex and creates arrays and objects that don't serve any useful purpose. – Duncan C May 22 '14 at 21:53
  • You don't need the lats and longs in order. If you subtract one from the other and take the absolute value (`fabs()`) the result will be the difference between them (the distance.) – Duncan C May 22 '14 at 21:55
  • I got rid of the pin on the user's location with that if statement there, but I like your approach better; I'll change it. I created the array because I have a couple other maps that will have several annotations, so I decided to just use arrays this time and copy the method instead of writing separate ones. Thank you both very much. – kerbelda May 23 '14 at 02:00

2 Answers2

1

So do some thinking on this.

If you don't want the user's location to be shown, turn it off the show current location flag for the map.

Turn on the location manager and ask for location updates.

in the location manager delegate method that gives you location updates, take the user's new location, and average it with the annotation you want to show (lat1 + lat2)/2, (long1 + long2)/2.

That'll give you a center-point between the 2. Then take the latitude delta between those two points, the longitude delta between those two points, multiply those deltas by a small scaling factor like 1.1 or 1.2, so the two points aren't right at the edges of the screen,, and feed those numbers into MKCoordinateSpanMake, and use the resulting span, plus the center point, to create a coordinate region, and set the map to that coordinate region.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Thanks Duncan, I'll take a look at the documentation and come back with some results tomorrow. I DO want the user location to show, just not with the red pin on top (like in the image). – kerbelda May 22 '14 at 06:02
  • Did what you said and got it to work, thanks! Updated my original post to include the code. – kerbelda May 22 '14 at 21:13
0

For swift 3:

let annotation = MKPointAnnotation();
    annotation.coordinate = CLLocationCoordinate2DMake(LATITUDE, LONGITUDE);
    self.mapView.addAnnotation(annotation);


    let userlongitude = location.coordinate.longitude
    let userlatitude = location.coordinate.latitude
    let newDistance = CLLocation(latitude: userlatitude, longitude: userlongitude).distance(from: CLLocation(latitude: annotation.coordinate.latitude, longitude: annotation.coordinate.longitude))
    let region = MKCoordinateRegionMakeWithDistance(location.coordinate, 2 * newDistance, 2 * newDistance)
    let adjustRegion = self.mapView.regionThatFits(region)
    self.mapView.setRegion(adjustRegion, animated:true)

In above code "location" is CLLocation which holds the User current location.

Zulqarnain Mustafa
  • 1,615
  • 2
  • 22
  • 25