2012-07-18 79 views
0

我创建了MKMapView并使用了UIBarButtonItem替代zoom out以显示全部regions。它在iPhone模拟器上运行良好,但是当我尝试使用设备时,在3至5秒或10次之后,它的zoom返回current location。我不知道这里有什么问题。感谢您的任何建议。当我缩小时,MKMapView自动放大到当前位置

这下面是我的代码

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

你已经实现了地图视图的didUpdateUserLocation委托方法,并在那里您正在缩放地图以使用r的位置。

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

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

一种选择是保持boolean ivar(如didZoomToUserLocation),在该方法中,如果标记为NO,则只应缩放(即调用setRegion)。拨打setRegion后,在该方法中将标志设置为YES

在iOS 5及更高版本中,您也可以尝试setting the userTrackingModeMKUserTrackingModeFollow而不是手动缩放。我认为这种模式给用户一些自由,可以在继续跟踪用户的同时进行平移。

相关问题