MKMapView缩放用户位置和注释

时间:2013-02-07 20:40:54

标签: objective-c xcode

我希望我的MKMapView能够尽可能地缩放“用户位置”和注释。 地图已经显示了两者,但缩小到了整个国家。 我怎么能这样做?

我不知道为什么Annotation和Pin没有动画。

我的代码:

//Coords User
CLLocationCoordinate2D user_location;
user_location.latitude = mapView.userLocation.location.coordinate.latitude;
user_location.longitude = mapView.userLocation.location.coordinate.longitude;
//Coords Annotation
CLLocationCoordinate2D club_location;
club_location.latitude = [self.clubInfo.latitude doubleValue];
club_location.longitude = [self.clubInfo.longitude doubleValue];

MKMapPoint userPoint = MKMapPointForCoordinate(user_location);
MKMapPoint annotationPoint = MKMapPointForCoordinate(club_location);

MKMapRect userRect = MKMapRectMake(userPoint.x, userPoint.y, 0, 0);
MKMapRect annotationRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);

MKMapRect unionRect = MKMapRectUnion(userRect, annotationRect);

MKMapRect unionRectThatFits = [mapView mapRectThatFits:unionRect];
[mapView setVisibleMapRect:unionRectThatFits animated:YES];

// Add an annotation
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
annotation.coordinate = club_location;
annotation.title = self.clubInfo.clubName;
annotation.subtitle = @"Pin!";
[mapView addAnnotation:annotation]; // This was missing
[mapView selectAnnotation:annotation animated:YES];

MapView

日志:

userRect: {{134217728.0, 134217728.0}, {0.0, 0.0}}
annotationRect: {{99775488.0, 152579328.0}, {0.0, 0.0}}

unionRect: {{99775488.0, 134217728.0}, {34442240.0, 18361600.0}}

mapView.visibleMapRect: {{96025087.6, 116070015.1}, {41943040.7, 54657025.8}}

3 个答案:

答案 0 :(得分:8)

如果我理解得很好,您希望这两个注释在最大可能缩放时可见。我发现这个解决方案不需要任何计算

// You have coordinates
CLLocationCoordinate2D user = ...;
CLLocationCoordinate2D annotation = ...;
// Make map points
MKMapPoint userPoint = MKMapPointForCoordinate(user);
MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation);
// Make map rects with 0 size
MKMapRect userRect = MKMapRectMake(userPoint.x, userPoint.y, 0, 0);
MKMapRect annotationRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);
// Make union of those two rects
MKMapRect unionRect = MKMapRectUnion(userRect, annotationRect);
// You have the smallest possible rect containing both locations
MKMapRect unionRectThatFits = [mapView mapRectThatFits:unionRect];
[mapView setVisibleMapRect:unionRectThatFits animated:YES];

CoreLocation和MapKit结构很糟糕。

答案 1 :(得分:3)

对于稍后来这里的人:最简单的方法是(iOS7 +)这个:

假设您有@property MKMapView *mapViewMKPointAnnotation *theAnnotation,请致电:

[self.mapView showAnnotations:@[theAnnotation, self.mapView.userLocation] animated:NO];

如果过早调用(即尚未设置self.mapView.userLocation时),这可能会导致一些问题。如果是这样,您可以拨打viewWillAppear

[self.mapView.userLocation addObserver:self forKeyPath:@"location" options:0 context:NULL];

然后,实施:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"location"]) {
        [self.mapView showAnnotations:@[theAnnotation, self.mapView.userLocation] animated:NO];
    }
}

这样你肯定已经确定了。不要忘记在viewWillDisappear中删除观察者:

[self.mapView.userLocation removeObserver:self forKeyPath:@"location"];

答案 2 :(得分:-1)

使用这4个类 - 它就像一个魅力!

//MapViewController.h file

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface MapViewController : UIViewController <CLLocationManagerDelegate>  {
    IBOutlet UIButton *buttonBack;
    IBOutlet MKMapView *mapView;
    IBOutlet UILabel *labelTitle;
    NSString *lon,*lat,*nickName;
    BOOL isFirstLaunch;
}
@property(nonatomic,retain) NSString *lon,*lat,*nickName;
@property(nonatomic,retain) IBOutlet UIButton *buttonBack;
@property(nonatomic,retain) IBOutlet UILabel *labelTitle;
@property(nonatomic,retain) IBOutlet MKMapView *mapView;
-(IBAction)buttonBackAction:(UIButton *)_btn;
-(void)zoomToFitMapAnnotations;
@end

// // MapViewController.m //

#import "MapViewController.h"
#import "Annotation.h"


@implementation MapViewController
@synthesize buttonBack,mapView,labelTitle;
@synthesize lon,lat,nickName;

// The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
 self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
 if (self) {
 // Custom initialization.
 }
 return self;
 }
 */
-(IBAction)buttonBackAction:(UIButton *)_btn{
    [self.navigationController popViewControllerAnimated:1];
}


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    CLLocationManager* locationManager = [[CLLocationManager alloc] init];
    [locationManager setDelegate:self];
    [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [locationManager startUpdatingLocation];
    NSLog(@"MapViewController");
    labelTitle.text = @"anscacorona.blogspot.in"
    CLLocationCoordinate2D location;
    location.latitude = [self.lat floatValue];
    location.longitude = [self.lon floatValue];

    Annotation *annotation = [[Annotation alloc] init];
    annotation.theCoordinate = location;
    annotation.theTitle = [NSString stringWithFormat:@"%@",labelTitle.text];

    [mapView addAnnotation:annotation];
    [annotation release];
    mapView.showsUserLocation = 1;

    [self zoomToFitMapAnnotations];
    [super viewDidLoad];
}

// Shows the location of both users. called when the device location changes to move the map accordinly. necessary ONLY once when the window is opened. afterwards the user can move the map as he choises. 
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    if (isFirstLaunch) {
        CLLocationCoordinate2D topLeftCoord;
        CLLocationCoordinate2D bottomRightCoord;

        topLeftCoord.longitude = fmin([self.lon floatValue], newLocation.coordinate.longitude);
        topLeftCoord.latitude = fmax([self.lat floatValue], newLocation.coordinate.latitude);

        bottomRightCoord.longitude = fmax([self.lon floatValue], newLocation.coordinate.longitude);
        bottomRightCoord.latitude = fmin([self.lat floatValue], newLocation.coordinate.latitude);

        MKCoordinateRegion region;
        region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
        region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
        region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.5; // Add a little extra space on the sides
        region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.5;  // Add a little extra space on the sides

        region = [mapView regionThatFits:region];
        [mapView setRegion:region animated:YES];
        isFirstLaunch = NO;
    }

}

-(void)zoomToFitMapAnnotations
{
    if([mapView.annotations count] == 0)
        return;

    CLLocationCoordinate2D topLeftCoord;
    CLLocationCoordinate2D bottomRightCoord;
    topLeftCoord.longitude = fmin(mapView.userLocation.location.coordinate.longitude, [self.lon floatValue]);
    topLeftCoord.latitude = fmax(mapView.userLocation.location.coordinate.latitude, [self.lat floatValue]);

    bottomRightCoord.longitude = fmax(mapView.userLocation.location.coordinate.longitude, [self.lon floatValue]);
    bottomRightCoord.latitude = fmin(mapView.userLocation.location.coordinate.latitude, [self.lat floatValue]);


    MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };

    CLLocationCoordinate2D userCoord = {[self.lat floatValue],[self.lon floatValue]};
    region.center = userCoord;
    region.span.latitudeDelta = 0.05f;//fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; // Add a little extra space on the sides
    region.span.longitudeDelta = 0.05f;//fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1;  // Add a little extra space on the sides

    [mapView setRegion:region animated:YES];
    [mapView regionThatFits:region];
}
/*
 // Override to allow orientations other than the default portrait orientation.
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
 // Return YES for supported orientations.
 return (interfaceOrientation == UIInterfaceOrientationPortrait);
 }
 */

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc. that aren't in use.
}
#pragma mark - View Lifecycle

-(void)viewWillAppear:(BOOL)animated{
    isFirstLaunch=YES;
}

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


- (void)dealloc {

    [super dealloc];
}


@end

// anotation classes- Annotation.h

#import <MapKit/MapKit.h>


@interface Annotation : NSObject  <MKAnnotation>{
    CLLocationCoordinate2D theCoordinate;
    NSString *theTitle;
    NSString *restId;
    NSString *theSubtitle;
}
@property(nonatomic,retain) NSString *restId;
@property(nonatomic,retain) NSString *theTitle;
@property(nonatomic,retain) NSString *theSubtitle;
@property CLLocationCoordinate2D theCoordinate;
@end

// Annotation.m

#import "Annotation.h"


@implementation Annotation
@synthesize theCoordinate,theTitle,theSubtitle,restId;
- (CLLocationCoordinate2D)coordinate;
{
    return theCoordinate; 
}

// required if you set the MKPinAnnotationView's "canShowCallout" property to YES
- (NSString *)title
{
    return theTitle;
}

// optional
- (NSString *)subtitle
{
    return theSubtitle;
}

- (void)dealloc
{
    [super dealloc];
}

@end