iOS 中的离线地图
Offline Map in iOS
我非常需要为我的应用程序制作离线地图,因为它主要是为泰国制作的,那里通常很难获得互联网连接。我现在正在为我的 MKTileOverlay
使用 OpenStreetMap,但在实现它以供离线使用时遇到问题。我找到了一个教程,说要子类化 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];
}
在我的 MKTileOverlay 子类中,我有:
- (NSURL *)URLForTilePath:(MKTileOverlayPath)path {
return [NSURL URLWithString:[NSString stringWithFormat:@"http://tile.openstreetmap.org/{%ld}/{%ld}/{%ld}.png", (long)path.z, (long)path.x, (long)path.y]];
}
- (void)loadTileAtPath:(MKTileOverlayPath)path
result:(void (^)(NSData *data, NSError *error))result
{
if (!result) {
return;
}
NSData *cachedData = [self.cache objectForKey:[self URLForTilePath:path]];
if (cachedData) {
result(cachedData, nil);
} else {
NSURLRequest *request = [NSURLRequest requestWithURL:[self URLForTilePath:path]];
[NSURLConnection sendAsynchronousRequest:request queue:self.operationQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
result(data, connectionError);
}];
}
}
问题是什么都没有加载,除非我注释掉子类中的代码。我哪里搞砸了?
您需要一个用图像响应您的 http://<domain>/{z}/{x}/{y}/image.png
的服务器,或者您必须使用路径 /tiles/{z}/{x}/{y}/image.png
.
将图块保存在您的应用程序包中
我也有兴趣在离线模式下加载地图。
首先,我在 gmapcatcher.
的帮助下将图块下载到我的本地系统(计算机)中
您可以获得一些关于 gmapcatcher here. And you can download this application here 的信息。
如果您想下载文件,还有一件重要的事情离线检查,有很多方法可以保存文件。对于这种情况 select OSM 在设置 window 中(位于左侧,您将在设置 window 中指定要下载的路径)
只需将创建的 tiles 文件夹添加到项目中即可。
我不知道 objective-c 所以我在 swift 中实施并且我只发布了该代码。
这是代码
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
self.mapView.delegate = self
let baseURL = NSBundle.mainBundle().bundleURL.absoluteString
let urlTemplate = baseURL.stringByAppendingString("OSM_sat_tiles/{z}/{x}/{y}.png")
//OSM_sat_tiles is the folder name which has the tiles.
let layer = MKTileOverlay(URLTemplate: urlTemplate)
layer.canReplaceMapContent = true
self.mapView.addOverlay(layer)
}
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKTileOverlay {
let renderer = MKTileOverlayRenderer(overlay:overlay)
renderer.alpha = 0.8
return renderer
}
return MKTileOverlayRenderer(overlay: overlay)
}
}
我会简要介绍一下代码。
在 viewDidLoad 委托方法中,我通过提供 tiles 文件夹的路径来创建 MKTileOverlay。因为我已经放在项目中,所以它会在包中。
并且在 rendererForOverlay 委托方法中我返回
MKTileOverlayRenderer.
我非常需要为我的应用程序制作离线地图,因为它主要是为泰国制作的,那里通常很难获得互联网连接。我现在正在为我的 MKTileOverlay
使用 OpenStreetMap,但在实现它以供离线使用时遇到问题。我找到了一个教程,说要子类化 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];
}
在我的 MKTileOverlay 子类中,我有:
- (NSURL *)URLForTilePath:(MKTileOverlayPath)path {
return [NSURL URLWithString:[NSString stringWithFormat:@"http://tile.openstreetmap.org/{%ld}/{%ld}/{%ld}.png", (long)path.z, (long)path.x, (long)path.y]];
}
- (void)loadTileAtPath:(MKTileOverlayPath)path
result:(void (^)(NSData *data, NSError *error))result
{
if (!result) {
return;
}
NSData *cachedData = [self.cache objectForKey:[self URLForTilePath:path]];
if (cachedData) {
result(cachedData, nil);
} else {
NSURLRequest *request = [NSURLRequest requestWithURL:[self URLForTilePath:path]];
[NSURLConnection sendAsynchronousRequest:request queue:self.operationQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
result(data, connectionError);
}];
}
}
问题是什么都没有加载,除非我注释掉子类中的代码。我哪里搞砸了?
您需要一个用图像响应您的 http://<domain>/{z}/{x}/{y}/image.png
的服务器,或者您必须使用路径 /tiles/{z}/{x}/{y}/image.png
.
我也有兴趣在离线模式下加载地图。
首先,我在 gmapcatcher.
的帮助下将图块下载到我的本地系统(计算机)中您可以获得一些关于 gmapcatcher here. And you can download this application here 的信息。
如果您想下载文件,还有一件重要的事情离线检查,有很多方法可以保存文件。对于这种情况 select OSM 在设置 window 中(位于左侧,您将在设置 window 中指定要下载的路径)
只需将创建的 tiles 文件夹添加到项目中即可。
我不知道 objective-c 所以我在 swift 中实施并且我只发布了该代码。
这是代码
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
self.mapView.delegate = self
let baseURL = NSBundle.mainBundle().bundleURL.absoluteString
let urlTemplate = baseURL.stringByAppendingString("OSM_sat_tiles/{z}/{x}/{y}.png")
//OSM_sat_tiles is the folder name which has the tiles.
let layer = MKTileOverlay(URLTemplate: urlTemplate)
layer.canReplaceMapContent = true
self.mapView.addOverlay(layer)
}
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKTileOverlay {
let renderer = MKTileOverlayRenderer(overlay:overlay)
renderer.alpha = 0.8
return renderer
}
return MKTileOverlayRenderer(overlay: overlay)
}
}
我会简要介绍一下代码。
在 viewDidLoad 委托方法中,我通过提供 tiles 文件夹的路径来创建 MKTileOverlay。因为我已经放在项目中,所以它会在包中。
并且在 rendererForOverlay 委托方法中我返回 MKTileOverlayRenderer.