3

我希望我的 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];

地图视图

日志:

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}}
4

3 回答 3

9

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

// 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 结构是地狱。

于 2013-02-07T21:33:31.883 回答
5

对于以后来这里的任何人:执行此操作的最短方法是(iOS7+):

假设您有一个 @propertyMKMapView *mapView和一个MKPointAnnotation *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"];
于 2015-02-26T14:45:14.367 回答
-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

//注释类-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

//注解.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
于 2013-02-07T21:00:10.300 回答