我非常需要为我的应用做离线地图,因为它主要是为泰国制作的,因为泰国通常很难连接互联网.我现在正在使用OpenStreetMap
我的MKTileOverlay
但是在实现它以供离线使用时遇到问题.我找到了一个教给子类的教程MKTileOverlay
.所以,在我ViewController
的地图上我有:
- (void)viewWillAppear:(BOOL)animated {
CLLocationCoordinate2D coord = {.latitude = 15.8700320, .longitude = 100.9925410};
MKCoordinateSpan span = {.latitudeDelta = 3, .longitudeDelta = 3};
MKCoordinateRegion region = {coord, span};
[mapView setRegion:region];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"Map";
NSString *template = @"http://tile.openstreetmap.org/{z}/{x}/{y}.png";
self.overlay = [[XXTileOverlay alloc] initWithURLTemplate:template];
self.overlay.canReplaceMapContent = YES;
[mapView addOverlay:self.overlay level:MKOverlayLevelAboveLabels];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id)overlay {
return [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay];
}
Run Code Online (Sandbox Code Playgroud)
在我的子类中MKTileOverlay
,我有:
- (NSURL *)URLForTilePath:(MKTileOverlayPath)path { …
Run Code Online (Sandbox Code Playgroud) 我在我的 iOS 项目中使用 MapKit 有一个自定义的 MKTileOverlay,它大部分时间都可以正常工作。但是,在放大/缩小几次并平移地图后,一些图块没有被绘制。
起初我认为这是一个没有加载瓷砖的简单情况,所以我对 MKTileOverlay 进行了子类化并在控制台中添加了日志记录。它表明所有瓷砖都被完美地加载并交付到结果块。
由于我的想法不多了,我创建了一个本地图块生成器,它只返回带有 x/y/z 路径和绘制的框架的图像,以查看缺少哪些图块。
不幸的是,即使使用本地生成的图块,问题仍然存在,因此它与 Internet 连接无关。另一个奇怪的行为是,如果我有两个自定义叠加层,它们将是完全相同的图块,但不会在两个叠加层上呈现。
我现在能想到的唯一解决方案是将 tile 渲染器子类化并确保显示所有内容,因为无法知道 tile 未呈现。然而,这听起来像是很多工作和“重新发明轮子”的任务......
我有问题要在MKMapKit中加载512x512px图块.服务器提供512x512 .jpeg磁贴.
我在MKMapView中找不到自定义视网膜图块的任何解决方案或示例实现.
我所做的:
当我将它们加载到MKMapView中时
overlay = [[MKTileOverlay alloc] initWithURLTemplate:template];
overlay.tileSize = CGSizeMake(512.0f, 512.0f);
[_mapView insertOverlay:overlay atIndex:MAP_OVERLAY_INDEX_TILE level:MKOverlayLevelAboveLabels];
Run Code Online (Sandbox Code Playgroud)
...瓷砖缩放正确但只加载了一半(不仅在视觉上 - 我嗅探了请求并且缺少了瓷砖)
同
overlay = [[MKTileOverlay alloc] initWithURLTemplate:template];
overlay.tileSize = CGSizeMake(256.0f, 256.0f);
[_mapView insertOverlay:overlay atIndex:MAP_OVERLAY_INDEX_TILE level:MKOverlayLevelAboveLabels];
Run Code Online (Sandbox Code Playgroud)
...显示所有图块但缩放不正确
这是我的绘图方法:
(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay
{
MKOverlayRenderer *overlayRenderer = nil;
if([overlay isKindOfClass:MKTileOverlay.class])
{
overlayRenderer = [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay];
}
return overlayRenderer;
}
Run Code Online (Sandbox Code Playgroud)
... overlayRenderer.contentScaleFactor总是1 ...无论是什么tileSize(iOS模拟器7.1视网膜)
有什么建议?
最好的问候,史蒂夫
我一直在iOS 7中使用MKMapView尝试设置并以编程方式获取缩放级别,以便在我离线时下载和重用地图图块.
因为我无法将整个地图下载到我的手机中,所以我只是按照适当的缩放级别下载了几个平铺,然后我修复了缩放级别并使用了思想MKTileOverlay和MKTileOverlayRenderer的平铺.
我尝试使用Troybrant的算法(http://troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview),但它对我来说效果不佳.它无法正确建立缩放级别.
所以我创建了一个我自己的工作正常.
关于我自己的方法的一些解释:
在最大地图缩放级别(20),您将看到每个地图点的比例为1:1.整个地图将有256*2 ^ 20点.
在视网膜显示器中,在地图点和像素之间存在2.0比例因子.
Apple地图的缩放级别可以从3到19(最小和最大)不等
然后有一个简单的反向规则:
有了这些信息,我们的想法是设置MKMapView的visibleRect属性:
visibleRect width points = 2.0 * mapView.bounds.size.width * 2^(20-zoom)
Run Code Online (Sandbox Code Playgroud)
使用该公式,我已经能够将我的地图居中并适当地应用它们缩放级别.
正如Troybrant所做的那样,我使用以下方法创建了一个类别:
@interface MKMapView (ZoomLevel)
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
zoomLevel:(NSUInteger)zoomLevel
animated:(BOOL)animated;
@end
@implementation MKMapView (ZoomLevel)
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
zoomLevel:(NSUInteger)zoomLevel
animated:(BOOL)animated
{
MKMapPoint centrePoint = MKMapPointForCoordinate(centreCoord);
CGFloat rectWidth = 2.0 * self.bounds.size.width * pow(2, 20-zoomLevel);
CGFloat rectHeight = 2.0 * self.bounds.size.height * pow(2, 20-zoomLevel);
MKMapRect visibleRect = MKMapRectMake(centrePoint.x-rectWidth/2, centrePoint.y-rectHeight/2, rectWidth, …
Run Code Online (Sandbox Code Playgroud) 我使用自定义 TileOverlay 开发了 iOS 地图应用程序,它从我们自己的服务器加载图块。我扩展了 TileOverlay 类,它获取图块数据如下:
override func loadTile(at path: MKTileOverlayPath, result: @escaping (Data?, Error?) -> Void)
{
let url = self.url(forTilePath: path)
if let cachedData = cache.object(forKey: url as AnyObject) as? NSData
{
result(cachedData as Data, nil)
} else {
let session = URLSession.shared
let request = NSURLRequest(url: url)
let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
if let data = data {
self.cache.setObject(data as AnyObject, forKey: url as AnyObject)
}
result(data, …
Run Code Online (Sandbox Code Playgroud) 我MKMapView
正在处理MKTileOverlay
来自本地数据库的显示图块。它工作正常。
然后我用来MKDirections
获得两个坐标之间的方向并绘制这样的路线:
MKRoute *route = response.routes.lastObject;
MKPolyline *polyline = route.polyline;
// Draw path on overlay
[self.mapView insertOverlay:polyline aboveOverlay:self.tileOverlay];
Run Code Online (Sandbox Code Playgroud)
但是当我缩放以查看线条时,它看起来没有平铺背景(通常从MKTileOverlay
(存储到self.tileOverlay
)加载)。我加入了一个图像以更好地查看。
我还制作了此代码来呈现叠加层:
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
if ([overlay isKindOfClass:[MKTileOverlay class]]) {
return [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay];
}
else if ([overlay isKindOfClass:[MKPolyline class]]) {
MKPolylineRenderer *lineView = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
lineView.strokeColor = [UIColor greenColor];
lineView.lineWidth = 3;
return lineView;
}
return nil;
}
Run Code Online (Sandbox Code Playgroud)
这就像渲染线的“瓷砖”隐藏从MKTileOverlay
. 我怎样才能:
- 指定MKPolyline
叠加层必须是透明的?
- …
ios ×5
mapkit ×4
mkmapview ×2
mkpolyline ×1
objective-c ×1
offline ×1
retina ×1
scale ×1
swift ×1
zoom ×1