0

我已经创建MKMapView并用于UIBarButtonItem显示zoom out所有regions. 它在 iPhone 模拟器上运行良好,但是当我在设备上尝试时,它zoom会在 3-5 秒或有时 10 秒后恢复current location。我不知道这里出了什么问题。感谢您的任何建议。

以下是我的代码

MapViewController.h

#import <UIKit/UIKit.h>
#import "MapListViewController.h"

@class MCLocation;

@interface MapViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate, MapListViewControllerDelegate>
{
    CLLocationManager *locationManager;
    NSArray *locations;

    __weak IBOutlet MKMapView *worldView;
    __weak IBOutlet UISegmentedControl *mapTypeControl;
}
@property (nonatomic, strong) MCLocation *item;
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;

- (IBAction)changeMapType:(id)sender;
- (void)zoomLocation:(CLLocationCoordinate2D)i;

@end

MapViewController.m

#import "MapViewController.h"
#import "MCLocation.h"
#import "MCLocationStore.h"
#import "MapDetailViewController.h"


#define METERS_PER_MILE 1609.344

@interface MapViewController ()

@end

@implementation MapViewController
@synthesize item;
@synthesize fetchedResultsController;
@synthesize managedObjectContext;

- (id)init 
{
    self = [super initWithNibName:@"MapViewController" bundle:nil];
    if (self) {
        [[self navigationItem] setTitle:@"Map"];

        UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStyleBordered target:self action:nil];
        [[self navigationItem] setBackBarButtonItem:backButton];

        UIImage *userImage = [UIImage imageNamed:@"User.png"];
        UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithImage:userImage style:UIBarButtonItemStyleBordered target:self action:@selector(showUser)];

        UIImage *locationImage = [UIImage imageNamed:@"Pin.png"];
        UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithImage:locationImage style:UIBarButtonItemStyleBordered target:self action:@selector(showLocation)];

        [[self navigationItem] setLeftBarButtonItems:leftButton];
        [[self navigationItem] setRightBarButtonItems:rightButton];
    }
    return self;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    return [self init];
}

- (MKCoordinateRegion)regionForAnnotations:(NSArray *)annotations
{
MKCoordinateRegion region;

if ([annotations count] == 0) {
    region = MKCoordinateRegionMakeWithDistance(worldView.userLocation.coordinate, 1000, 1000);

} else if ([annotations count] == 1) {
    id <MKAnnotation> annotation = [annotations lastObject];
    region = MKCoordinateRegionMakeWithDistance(annotation.coordinate, 1000, 1000);

} else {
    CLLocationCoordinate2D topLeftCoord;
    topLeftCoord.latitude = -90;
    topLeftCoord.longitude = 180;

    CLLocationCoordinate2D bottomRightCoord;
    bottomRightCoord.latitude = 90;
    bottomRightCoord.longitude = -180;

    for (id <MKAnnotation> annotation in annotations)
    {
        topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
        topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
        bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
        bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
    }

    MKCoordinateSpan span;
    span.latitudeDelta = 2.0;
    span.longitudeDelta = 0.5;

    region.span = span;
    region.center = worldView.userLocation.coordinate;

return [worldView regionThatFits:region];
}

- (IBAction)showUser 
{
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(worldView.userLocation.coordinate, 250, 250);
    [worldView setRegion:[worldView regionThatFits:region] animated:YES];
}

- (IBAction)showLocation 
{
    MKCoordinateRegion region = [self regionForAnnotations:locations];
    [worldView setRegion:region animated:YES];
}

- (void)updateLocations 
{
    if (locations != nil) {
        [worldView removeAnnotations:locations];
    }

    locations = [self.fetchedResultsController fetchedObjects];
    [worldView addAnnotations:locations];
}

- (void)zoomLocation:(CLLocationCoordinate2D)i 
{
    CLLocationCoordinate2D zoomLocation = i;

    MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 0.5*METERS_PER_MILE, 0.5*METERS_PER_MILE);

    MKCoordinateRegion adjustedRegion = [worldView regionThatFits:viewRegion];

    [worldView setRegion:adjustedRegion animated:YES];
}

- (void)performFetch 
{
    NSError *error;
    if (![self.fetchedResultsController performFetch:&error]) {
        FATAL_CORE_DATA_ERROR(error);
        return;
    }
}

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

    [worldView setShowsUserLocation:YES];

    [self performFetch];
    [self loadMapTypePref];
    [self updateLocations];

    // If we have locations, then show them on the map. If there are no
// locations, then let the map view figure out how to center on the
// user's position. It will usually do a pretty good job.
    if ([locations count] > 0) {
        [self showLocation];
    }

    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        [mapTypeControl setHidden:YES];

        CLLocationCoordinate2D coord = [item coordinate];
        [worldView setCenterCoordinate:coord animated:NO];
        [self zoomLocation:coord];
    }
}

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

- (void)dealloc 
{
    [locationManager setDelegate:nil];
}

#pragma mark - MKMapViewDelegate

- (void)mapView:(MKMapView *)mapView 
didUpdateUserLocation:(MKUserLocation *)userLocation 
{
    CLLocationCoordinate2D loc = [userLocation coordinate];
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(loc, 250, 250);
    [worldView setRegion:region animated:YES];
}

- (MKAnnotationView *)mapView:(MKMapView *)mapView 
        viewForAnnotation:(id<MKAnnotation>)annotation 
{   
    static NSString *LocationIdentifier = @"Location";
    MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[worldView dequeueReusableAnnotationViewWithIdentifier:LocationIdentifier];

    if ([annotation isKindOfClass:[MCLocation class]]) {
        if (!annotationView) {
            annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:LocationIdentifier];
        } 
        [annotationView setAnnotation:annotation];
        [annotationView setPinColor:MKPinAnnotationColorRed];
        [annotationView setEnabled:YES];
        [annotationView setAnimatesDrop:YES];
        [annotationView setCanShowCallout:YES];
        [annotationView setCalloutOffset:CGPointMake(-5, 5)];
        [annotationView setUserInteractionEnabled:YES];

        UIButton *rightButton = nil;
        UIImage *logoImage = [UIImage imageNamed:@"monkcup-map-pin.png.png"];
        UIImageView *leftButton = [[UIImageView alloc] initWithImage:logoImage];

        rightButton = [UIButton buttonWithType:UIButtonTypeInfoLight];

        [annotationView setRightCalloutAccessoryView:rightButton];
        [annotationView setLeftCalloutAccessoryView:leftButton];

        return annotationView;
    } else {
        [[worldView userLocation] setTitle:@"You're here"];
    }

    return nil;
}

- (void)mapView:(MKMapView *)mapView 
 annotationView:(MKAnnotationView *)view 
calloutAccessoryControlTapped:(UIControl *)control 
{
    // Call out code
}


#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{
    NSTimeInterval t = [[newLocation timestamp] timeIntervalSinceNow];
    if (t < -180) {
        return;
    }
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error 
{
    //
}


#pragma mark - Fetched results controller

- (NSFetchedResultsController *)fetchedResultsController 
{
    if (fetchedResultsController) {
    return fetchedResultsController;
    }

    // Create and configure a fetch request with the Book entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    MCLocationStore *ls = [MCLocationStore sharedStore];
    self.managedObjectContext = ls.context;

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"MCLocation" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Create the sort descriptors array.
    NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"storeName" ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sd, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];

    // Create and initialize the fetch results controller.
    fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"MapView"];

    return fetchedResultsController;
}

@end
4

1 回答 1

4

您已经实现了地图视图的didUpdateUserLocation委托方法,并在其中将地图缩放到用户的位置。

只要设备获得位置更新,就会调用该委托方法。

因此,在您缩放或平移之后,如果有另一个位置更新,则调用委托方法并将其缩放回用户位置。

一种选择是保留一个布尔值 ivar(比如),并且在该方法中,如果标志是didZoomToUserLocation,您应该只缩放(即 call ) 。调用后在该方法中设置标志。setRegionNOYESsetRegion

在 iOS 5 及更高版本中,您还可以尝试将 设置userTrackingModeMKUserTrackingModeFollow而不是手动缩放。我认为该模式为用户提供了一些自由平移,同时仍跟随用户。

于 2012-07-18T11:45:09.847 回答