【问题标题】:Offline Cache of Map地图离线缓存
【发布时间】:2016-12-16 00:28:43
【问题描述】:

我非常需要为我的应用制作离线地图,因为它主要是为泰国制作的,那里通常很难获得互联网连接。我现在正在为我的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);
        }];
    }
}

问题是根本没有加载任何东西,除非我注释掉子类中的代码。我在哪里搞砸了?

【问题讨论】:

  • 你在哪里调用 loadTileAtPath 方法?
  • 我没有调用它,因为我不确定如何调用它,因为它需要一条路径,而我不知道如何获取它。 @ldindu
  • @ldindu 我将如何传递地图最初加载到它的路径?使用正常的 initWithUrlTemplate 它只是发生了,但我只是不知道这个设置。
  • 如何创建 MKTileOverlayPath 以传递给方法?
  • 在[mapView addOverlay:self.overlay level:MKOverlayLevelAboveLabels];之后,需要调用[self.overlay loadTitlePath:"Your path" result: "Your completion block"]

标签: ios mapkit openstreetmap offline-caching mktileoverlay


【解决方案1】:

在我们公司,我们选择使用MapBox 进行离线映射。

在那里,您可以使用 MapBox Studio 设计和设置自己的地图样式,然后将地图(在选定的缩放级别范围内)导出到外部文件中。我们的大小约为 40Mb。

从那里,您可以使用MapBox iOS SDK 轻松将其添加到您的应用中。

(免责声明:不,我不为他们工作!我们特别选择他们是因为能够定义我们自己的陆地/海洋颜色和样式,并且能够将地图文件包含在我们的 Xcode 项目中,并且可以使用离线。)

我非常感谢您的确切问题是如何让 OpenStreetMap 自己的地图离线,但我希望这对您有用。

【讨论】:

    【解决方案2】:

    您似乎没有填充缓存。总是空的?

    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) {
    
            // Instantiate a new cache if we don't already have one.
            if (!self.cache) self.cache = [NSCache new];
    
            // Add the data into the cache so it's there for next time.
            if (data) {
                [self.cache setObject:data forKey:[self URLForTilePath:path]];
            }
    
            result(data, connectionError);
        }];
    }
    

    我认为这将解决您的问题。请记住,NSCache 不会持久保存到磁盘(仅保存到内存),因此虽然它确实在后台运行的应用程序中存在,但如果您想要完全离线功能(可能是核心数据),从长远来看,您将需要更复杂的东西。

    【讨论】:

      猜你喜欢
      • 2011-01-27
      • 1970-01-01
      • 1970-01-01
      • 2012-05-20
      • 2013-05-19
      • 1970-01-01
      • 1970-01-01
      • 2011-08-31
      相关资源
      最近更新 更多