3

我一直存在 MKMapView 的内存泄漏问题(已报告给 Apple,但没有回应),因此作为一种解决方法,我尝试只分配一个 MKMapView 并重新使用该映射而不是重新分配一个新映射。我遇到的问题是我还不能将 MKMapView 重置为它开始的视图。我假设因为我在美国工作,我最初得到这样的看法:

美国地图
(来源:cprince.com

使用此代码:

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 的按钮时,我得到以下地图(还没有惊喜):

我家的地图
(来源:cprince.com

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

海洋地图
(来源:cprince.com

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

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

setRegion 在 addSubview 之后还是之前都没有关系。也就是说,下面的更改并不能纠正问题:

- (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 设为静态而不是实例变量,这并没有显着改变情况。(我在下面报告了默认区域的纬度/经度)。这是地图中的结果:

海洋地图
(来源:cprince.com

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

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

1 回答 1

3

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

如果要在第一次设置defaultRegion后保存MKMapView,请设置的delegate属性MKMapView然后实现:

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

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


老答案:

当您设置defaultRegion时,这是一个实例变量。因此,当您关闭视图时,它就会丢失。当您回到地图(即firstTimeis NO)时,defaultRegion从未初始化,因此为 0,0,因此位于大西洋中部。

您显然没有保存defaultRegion(通常您有一个协议将其传递回主视图控制器),这使得应用程序很难知道当您再次选择主视图中的项目时该做什么。

于 2013-03-22T00:20:47.967 回答