17

当我的 iPhone 应用程序像这样关闭时,我将地图区域保存到用户默认值中:

MKCoordinateRegion region = mapView.region;
[[NSUserDefaults standardUserDefaults] setDouble:region.center.latitude forKey:@"map.location.center.latitude"];
[[NSUserDefaults standardUserDefaults] setDouble:region.center.longitude forKey:@"map.location.center.longitude"];
[[NSUserDefaults standardUserDefaults] setDouble:region.span.latitudeDelta forKey:@"map.location.span.latitude"];
[[NSUserDefaults standardUserDefaults] setDouble:region.span.longitudeDelta forKey:@"map.location.span.longitude"];

当应用再次启动时,Ш 以相同的方式读取这些值,以便用户可以看到与上次完全相同的地图视图:

MKCoordinateRegion region;

region.center.latitude  = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.center.latitude"];
region.center.longitude = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.center.longitude"];
region.span.latitudeDelta  = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.latitude"];
region.span.longitudeDelta = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.longitude"];

NSLog([NSString stringWithFormat:@"Region read  : %f %f %f %f", region.center.latitude, region.center.longitude, region.span.latitudeDelta, region.span.longitudeDelta]);

[mapView setRegion:region];

NSLog([NSString stringWithFormat:@"Region on map: %f %f %f %f", mapView.region.center.latitude, mapView.region.center.longitude, mapView.region.span.latitudeDelta, mapView.region.span.longitudeDelta]);

我从用户默认值中读取的区域(毫不奇怪)与保存时完全相同。请注意,保存的内容直接来自地图,因此不会以任何方式进行转换。我用方法将它重新设置在地图上setRegion:,但后来就不一样了!

示例结果:

Region read  : 50.241110 8.891555 0.035683 0.042915<br>
Region on map: 50.241057 8.891544 0.050499 0.054932

有人知道为什么会这样吗?

4

9 回答 9

8

这里的问题是当您设置区域时,地图缩放级别“捕捉”到最近的缩放阈值。(我怀疑这些缩放阈值是您双击或两指点击时获得的缩放量)

因此,例如,如果地图显示缩放级别 1,并且您将区域设置为相同的跨度值:region = [mapView region]; [mapView setRegion:region];它将“捕捉”到1 级以上最近的缩放级别,即 2 级,您将缩小大约 1因子二。

原始海报的解决方法是在设置区域之前稍微减小跨度值,以便当视图捕捉到时,它会捕捉到它所在的缩放级别,而不是上面的缩放级别。

例如

region.span.latitudeDelta = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.latitude"] * 0.999;

region.span.longitudeDelta = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.longitude"] * 0.999;

如果用户一直在通过双击进行缩放(因此从一个阈值跳到另一个阈值),则效果很好,几乎可以将它们返回到相同的视图。

但是,如果他们捏缩放并且视图在缩放阈值之间的中间,它仍然会弹出到下一个级别。在这种情况下不太好,但目前还没有修复。

Apple 雷达上存在开放的错误,希望它会在未来的版本中得到修复。

于 2009-11-04T05:21:06.627 回答
2

我有同样的问题。这非常令人沮丧。似乎 MKMapView 的文档在有关数据类型的某些领域是不正确的。

如果您将区域参数设置为 (double)s,您将收到您遇到的错误。但是,如果传递区域参数(浮动),您将获得正确的行为。

所以试试

MKCoordinateRegion region = {{0.0f,0.0f},{0.0f,0.0f}};

region.center.latitude = (float) [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.center.latitude"];
region.center.longitude = (float) [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.center.longitude"];
region.span.latitudeDelta = (float) [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.latitude"];
region.span.longitudeDelta = (float) [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.longitude"];

mapView.region = region;
于 2009-09-06T18:59:55.660 回答
2

好的,所以我已经在这个问题上苦苦挣扎了一段时间,我认为我已经想出了一个受 Crufty 理论启发的有效解决方法(MKMapView 显示错误保存的区域)。基本上,如果您在地图视图完成其初始加载(完成“快速退出”行为)之后使用从 NSUserDefaults 获取的值设置地图视图区域,则地图区域将是您所期望的. 诀窍是在已初始化的地图视图下游某处的应用程序代码中找到一个挂钩。不漂亮,但它对我来说非常有用。感谢 Crufty 的洞察力。

于 2009-11-17T00:02:28.580 回答
2

也尝试存储态度,如

self.lastCameraAtitude = self.mapView.camera.altitude;

当你配置你的地图时

[self.mapView.camera setAltitude:self.lastCameraAtitude];

这将为同一地区的同一相机设置。在你的情况下,你只设置区域而不是相机。

于 2015-09-08T11:43:27.020 回答
0

我发现使用 0.9 而不是 0.999 的乘法因子取得了更大的成功,它有时仍会推出,但似乎更接近所需的缩放。仍然很想解决这个问题只是说我打败了它!哈哈

于 2011-06-22T01:28:34.137 回答
0

我无法验证这是否有效。其他人可以这样做吗?我敢打赌,您所看到的是将双打截断为浮点数的效果。在某些情况下,当这种情况发生在我身上时,我发现我可以将跨度乘以 0.9999 并重置区域,然后这就是我想要的。但并非所有地区 - 有时差异很大,差异高达 20%,尤其是对于小跨度。

于 2009-09-07T11:44:18.237 回答
0

最近我遇到了同样的事情。使用早期答案的见解,以下 swift 4 实现对我有用:

override func viewWillAppear(_ animated: Bool) {
    if isMovingToParentViewController {
        setInitialRegion()
        DispatchQueue.main.asyncAfter(deadline: .now(), execute: {
            self.setInitialRegion()
        })
    }
}

当地图视图控制器被推入视图时,这会设置一个初始缩放区域。对 setInitialRegion 的同步调用会将捕捉到的区域设置为缩放级别。对 setInitialRegion 的异步调用将设置确切的区域。仍然需要同步调用来删除缩放伪影。

于 2018-01-03T13:48:10.210 回答
0

这是一个正确编码和解码 MKCoordinateRegion 的 Swift 扩展:

extension MKCoordinateRegion {

    var encode:[String: AnyObject] {
        return ["center":
                   ["latitude": self.center.latitude,
                   "longitude": self.center.longitude],
                "span":
                   ["latitudeDelta": self.span.latitudeDelta,
                   "longitudeDelta": self.span.longitudeDelta]]
    }

    init?(decode: [String: AnyObject]) {

        guard let center = decode["center"] as? [String: AnyObject],
            let latitude = center["latitude"] as? Double,
            let longitude = center["longitude"] as? Double,
            let span = decode["span"] as? [String: AnyObject],
            let latitudeDelta = span["latitudeDelta"] as? Double,
            let longitudeDelta = span["longitudeDelta"] as? Double
        else { return nil }


        self.center = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
        self.span = MKCoordinateSpan(latitudeDelta: latitudeDelta, longitudeDelta: longitudeDelta)
    }
}

这是如何使用它:

// Save
NSUserDefaults.standardUserDefaults().setObject(mapView.region.encode, forKey: "mapRegion01")

// Restore
if let dict = NSUserDefaults.standardUserDefaults().dictionaryForKey("mapRegion01"),
    let myRegion = MKCoordinateRegion(decode: dict) {

    // do something with myRegion
}
于 2016-12-22T16:28:52.047 回答
-1

如果您在 InterfaceBuilder 中设置 MapView,请确保不要这样做:

_mapView = [[MKMapView alloc] init];

一旦我删除了这个初始化行,我的地图视图突然开始正确响应我发送的所有更新。我怀疑发生的事情是,如果你执行 alloc init,它实际上是在创建另一个没有在任何地方显示的视图。你在屏幕上看到的是你的笔尖初始化的那个。但是,如果您分配 init 一个新的,那么这就是其他地方的东西,它不会做任何事情。

于 2013-11-26T04:50:57.467 回答