MKMapView重置回世界观:重生

时间:2013-03-21 21:46:04

标签: iphone ios mkmapview

我一直在使用MKMapView持续存在内存泄漏问题(向Apple报告,但没有响应),所以作为一种解决方法,我试图分配一个MKMapView并重新使用该地图而不是重新分配新地图。我遇到的问题是我还没有能够将MKMapView重置为它开始的视图。我假设因为我在美国工作,我最初得到这样的观点:

map of USA http://www.cprince.com/stackoverflow/map1.png

使用此代码:

static MKMapView *map = nil;

- (void) showUserLocation {    
    [map setShowsUserLocation:YES];

    CLLocationCoordinate2D coord;

    coord.latitude = 39.0; // changed from original coords
    coord.longitude = -105.0;

    MKCoordinateRegion r = MKCoordinateRegionMakeWithDistance(coord, 1000, 1000);

    [map setRegion:r animated:YES];
}

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if (! map) {
        CGRect r = CGRectMake(20, 50, 196, 75);
        map = [[MKMapView alloc] initWithFrame:r];

        defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));
    } else {
        [map setRegion:defaultRegion animated:YES];
    }

    [self.view addSubview:map];
}

- (IBAction)annotateMap:(id)sender {
    [self showUserLocation];
}

当我点击调用annotateMap的按钮时,我得到以下地图(还没有惊喜):

map of my home http://www.cprince.com/stackoverflow/map2.png

然后,当我从这个视图中导航(使用导航控制器)然后重新进入视图(再次调用viewWillAppear,但这次它重新使用先前分配的MKMapView),我得到以下地图视图:

map of ocean http://www.cprince.com/stackoverflow/map3.png

当然我应该得到原始的默认区域,因为viewWillAppear的这一部分:

        defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));
    } else {
        [map setRegion:defaultRegion animated:YES];
    }

如果在addSubview之后或之前执行setRegion并不重要。也就是说,下面的更改不会更正探测器:

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    BOOL firstTime = NO;
    if (! map) {
        firstTime = YES;
        CGRect r = CGRectMake(20, 50, 196, 75);
        map = [[MKMapView alloc] initWithFrame:r];

        defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));
    }

    [self.view addSubview:map];
    if (! firstTime) {
        [map setRegion:defaultRegion animated:YES];
    }
}

并且使用MKMapRectWorld也无济于事:

defaultRegion = MKCoordinateRegionForMapRect(MKMapRectWorld);

这个问题也不是由于MKMapView的某种竞争条件造成的。如果我改变按钮的处理程序:

- (IBAction)annotateMap:(id)sender {
    defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));
    [self showUserLocation];
}

并等到地图在美国视图上找到我点击按钮之前,问题是一样的。

我正在使用iOS 6.1.2和XCode 4.6。

(完整的XCode项目位于http://www.cprince.com/stackoverflow/Map.zip)。

思想?

第一次改变

我将defaultRegion设为静态而不是实例变量,这并没有明显改变这种情况。 (我报告了下面默认区域的纬度/经度)。这是地图中的结果:

map of ocean http://www.cprince.com/stackoverflow/map4.png

为清楚起见,现在的代码是:

static MKMapView *map = nil;
static MKCoordinateRegion defaultRegion;

- (void) showUserLocation {    
    [map setShowsUserLocation:YES];

    CLLocationCoordinate2D coord;
    coord.latitude = 39.0; // changed from original
    coord.longitude = -105.0;

    MKCoordinateRegion r = MKCoordinateRegionMakeWithDistance(coord, 1000, 1000);

    [map setRegion:r animated:YES];
}

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    BOOL firstTime = NO;
    if (! map) {
        firstTime = YES;
        CGRect r = CGRectMake(20, 50, 196, 75);
        map = [[MKMapView alloc] initWithFrame:r];

        defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));

        NSLog(@"defaultRegion: center: lat: %f, long: %f; span: %f dlat: dlong: %f", defaultRegion.center.latitude, defaultRegion.center.longitude, defaultRegion.span.latitudeDelta, defaultRegion.span.longitudeDelta);
        //defaultRegion = MKCoordinateRegionForMapRect(MKMapRectWorld);
    }

    [self.view addSubview:map];
    if (! firstTime) {
        NSLog(@"defaultRegion: center: lat: %f, long: %f; span: %f dlat: dlong: %f", defaultRegion.center.latitude, defaultRegion.center.longitude, defaultRegion.span.latitudeDelta, defaultRegion.span.longitudeDelta);
        [map setRegion:defaultRegion animated:YES];
    }
}

- (IBAction)annotateMap:(id)sender {
    //defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));
    [self showUserLocation];
}

1 个答案:

答案 0 :(得分:3)

如果您为delegate制作MKMapView视图控制器并实施regionDidChangeAnimated,则会在第一次创建地图视图时看到centerCoordinate30, -40,但随后设置为37.178181, -96.054581(至少对美国用户而言)。在创建地图视图后,您显然不能立即依赖region和/或centerCoordinate。你必须给它一个重置region的机会,这显然是异步发生的。

如果您想在defaultRegion第一次设置MKMapView之后保存delegate,请设置MKMapView的{​​{1}}属性,然后执行:

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    static BOOL firstTime = YES;
    if (firstTime)
    {
        defaultRegion = mapView.region;
        firstTime = NO;
    }
}

注意,在viewWillDisappear上,由于您已将地图设为static,因此请确保nil地图的delegate(因为旧的视图控制器将消失) 。如果您希望继续将视图控制器的新实例设为MKMapViewDelegate,则只需在将地图视图重新添加到详细视图控制器的新实例时再次设置delegate


旧答案:

设置defaultRegion时,这是一个实例变量。因此,当您解除视图时,这会丢失。当你回到地图(即firstTimeNO)时,defaultRegion永远不会被初始化,因此是0,0,因此位于大西洋的中间。

你显然没有保存defaultRegion(通常你有一个协议将它传递回主视图控制器),这使得应用程序很难知道当你选择再次在主视图中显示项目。