当我的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"];
当app再次启动时,Ш以相同的方式读取这些值,以便用户可以看到与上次完全相同的地图视图:
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
有人知道为什么会这样吗?
答案 0 :(得分:8)
这里的问题是当您设置区域时,地图缩放级别“捕捉”到最近的缩放阈值。 (我怀疑这些缩放阈值是双击或双指敲击时获得的缩放量)
因此,如果地图显示缩放级别1,并且您将区域设置为相同的跨度值:region = [mapView region]; [mapView setRegion:region];
它将“捕捉”到最近的缩放级别以上级别1,即级别2,您将缩小大约两倍。
原始海报的解决方法是在设置区域之前稍微减小跨度值,这样当视图突然显示时,它会跳出到它所在的缩放级别,而不是上面的缩放级别。
e.g。
region.span.latitudeDelta = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.latitude"] * 0.999;
region.span.longitudeDelta = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.longitude"] * 0.999;
如果用户使用双击进行缩放(因此从阈值跳到阈值),则效果非常好,几乎完全将它们返回到同一视图。
但是,如果它们捏缩放并且视图位于缩放阈值之间,它仍会弹出到下一级别。在这种情况下不太好,但目前还没有解决。
苹果雷达上存在开放式漏洞,希望它将在未来版本中修复。
答案 1 :(得分:2)
我遇到了同样的问题。这非常令人沮丧。似乎MKMapView的文档在某些与数据类型有关的方面是不正确的。
如果将区域参数设置为(双)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;
答案 2 :(得分:2)
好的,所以我一直在努力解决这个问题已经有一段时间了,我认为我已经提出了一个有效的解决方案,受到了Crufty理论的启发(MKMapView show incorrectly saved region)。基本上,如果您在地图视图完成初始加载(完成“捕捉”行为)之后使用您从NSUserDefaults获取的值设置地图视图区域,则地图区域将是您期望的地图区域。诀窍是在地图视图下游某处初始化应用程序代码中找到一个钩子。不漂亮,但它对我来说很完美。感谢Crufty的洞察力。
答案 3 :(得分:0)
我无法验证这是否有效。其他人可以这样做吗?我愿意打赌,你所看到的是将你的双打截断为花车的效果。在某些情况下,当我遇到这种情况时,我发现我可以将跨度乘以0.9999并重置该区域,然后它就是我想要的。但并非所有地区 - 有时它都是非常不同的,高达20%不同,特别是对于小跨度。
答案 4 :(得分:0)
我发现使用乘法因子0.9而不是0.999取得了更大的成功,它仍然有时会推出,但似乎更接近所需的缩放。仍然喜欢解决这个问题,只是说我打败了它!哈哈
答案 5 :(得分:0)
还要尝试存储像
这样的态度self.lastCameraAtitude = self.mapView.camera.altitude;
当你配置你的地图时
[self.mapView.camera setAltitude:self.lastCameraAtitude];
这将设置相同的区域相同的相机。在你的情况下,你只设置区域而不是相机。
答案 6 :(得分:0)
这是一个Swift扩展,可以正确编码和解码MKCoordinateRegion:
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
}
答案 7 :(得分:0)
最近我遇到了同样的事情。使用前面答案中的见解,以下swift 4实现对我有用:
override func viewWillAppear(_ animated: Bool) {
if isMovingToParentViewController {
setInitialRegion()
DispatchQueue.main.asyncAfter(deadline: .now(), execute: {
self.setInitialRegion()
})
}
}
当地图视图控制器被推入视图时,这将设置初始缩放区域。对setInitialRegion的同步调用将设置一个捕捉到缩放级别的区域。对setInitialRegion的异步调用将设置确切的区域。仍需要同步调用来删除缩放工件。
答案 8 :(得分:-1)
如果在InterfaceBuilder中设置MapView,请确保不要这样做:
_mapView = [[MKMapView alloc] init];
我删除此初始化行后,我的地图视图突然开始正确响应我发送的所有更新。我怀疑发生的情况是,如果你执行alloc init,它实际上是在创建另一个没有在任何地方显示的视图。您在屏幕上看到的是您的笔尖初始化的那个。但是如果你为init分配一个新的,那么那就是其他的东西而且它不会做任何事情。