【问题标题】:Customizing MKTileOverlay for cached tiles为缓存切片自定义 MKTileOverlay
【发布时间】:2013-10-16 17:30:15
【问题描述】:

我正在尝试更新我的瓦片地图代码以使用 iOS 7 的 MKTileOverlayMKTileOverlayRenderer,我可以使用一些指针来让事情更好地工作。

首先,这里是 iOS6 代码:AppleTileOverlay.mTileOverlayView.m。当我将TileOverlayView 替换为一个在所有方面都相同的类时,这在iOS 7 中仍然可以很好地工作,除了它是MKOverlayRenderer 的子类而不是MKOverlayView

我正在测试的新部分是MKTileOverlay 的子类,唯一的方法是:

-(NSURL *)URLForTilePath:(MKTileOverlayPath)path {
    NSString *tileKey = [[NSString alloc] initWithFormat:@"%d%d%d", path.x, path.y, path.z];
    NSString *tilePath = [[NSBundle mainBundle] pathForResource:tileKey ofType:nil inDirectory:@"TileFolder"];

    NSURL *url;
    if (tilePath) {
        url = [NSURL fileURLWithPath:tilePath];
    }

    return url;
}

地图图块在大多数情况下加载良好,但日志中充满了如下消息:

Error loading URL (null): Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0x1b3e19e0 {NSUnderlyingError=0x1894d470 "bad URL", NSLocalizedDescription=bad URL}

来自为 URL 返回 nil 的方法。

所以问题是:我可以避免这些错误消息,还是应该坚持使用旧的覆盖类?

【问题讨论】:

  • 你找到解决办法了吗?
  • 没什么。我刚刚回到使用基于github.com/mtigas/iOS-MapLayerDemo 的旧版平铺叠加层,目前我不知道新版本是否更高效或更好。
  • 顺便说一句,我认为您的文件命名系统存在问题。瓷砖 x=1 y=11 z=5 和 x=11 y=1 z=5 都将命名为 1115.png,x=1, y=1 z=15 也是如此。也许您的图块永远不会与可以跨越的坐标重合,但如果有人将地图视图拉到一个意想不到的位置,他们可能会在错误的位置获得奇怪的图块。您最好在每个参数之间加上下划线,例如 1_11_5.png 以避免任何误解。
  • 非常好!到目前为止,我还没有看到这方面的问题,因为无论如何我的地图只在小范围内使用,但这将是一个非常简单的解决方法。好电话!

标签: mapkit mkoverlay


【解决方案1】:

我认为使用 Swift 2.0,URLForFilePath(...) 不能返回 nil,因为它不是可选的。

我设法解决了这个问题,使用 MKTileOverlay 子类检查上述有效的平铺路径并在平铺图像不可用时加载“虚拟”透明平铺。

override func URLForTilePath(path: MKTileOverlayPath) -> NSURL {

        let tileKey = String(format:"%d/%d/%d",path.z,path.x,path.y)

        let tilePath = NSBundle.mainBundle().pathForResource(tileKey, ofType: "png", inDirectory: "Maps/Map1880")

        let blankTilePath = NSBundle.mainBundle().pathForResource("blank", ofType: "png", inDirectory: "Maps")

        var url: NSURL

        if ((tilePath) != nil)
        {
            url =  NSURL.fileURLWithPath(tilePath!)
        } else {
            url = NSURL.fileURLWithPath(blankTilePath!)
        }

        return url;
    }

这不是很优雅,因为它会为每个不属于叠加层的图块加载空白图块。

不过,有一个更好的解决方案,感谢 Apple 开发者论坛上的用户:junkpile,尝试加载不存在的 overlay 图块的问题是 boundingMapRect默认设置为MKMapRectWorld,即整个世界。

要将其限制在所需的覆盖区域,请继承 MKTileOverlay

这是一个例子:

import MapKit
class CustomTileOverlay : MKTileOverlay {

        override var boundingMapRect: MKMapRect {
            get {
               //North-East Corner of region
                let lat1 = 53.46075
                let long1 = -1.92618
               //South-West Corner of region
                let lat2 = 53.43018
                let long2 = -1.992885

                //Convert to Coordinates
                let coord1 = CLLocationCoordinate2DMake(lat1,long1)
                let coord2 = CLLocationCoordinate2DMake(lat2,long2)

                //Convert to map points
                let p1 = MKMapPointForCoordinate (coord1);
                let p2 = MKMapPointForCoordinate (coord2);

                //Return the MKMapRect
               return MKMapRectMake(fmin(p1.x,p2.x), fmin(p1.y,p2.y), fabs(p1.x-p2.x), fabs(p1.y-p2.y)); 
            }
        }
    }

【讨论】:

    【解决方案2】:

    我猜你总是试图设置url,尽管没有一个真实有效的tilePath。添加一些调试,看看。

    【讨论】:

      【解决方案3】:

      当您查看地图上没有图块的区域时,是否会发生这种情况?

      因为你检查你是否有文件,然后如果文件不存在则不设置url,你返回nil。您应该将有效的 NSURL 返回到透明图像。

      【讨论】:

      • 是的,它仅适用于文件不存在的 URL。我检查的另一个覆盖类。我想在这种情况下最好保留旧的。
      • 我已将解决方案更新为我在应用程序中使用的解决方案。它对我来说效果很好,没有更多错误消息,但除了视觉比较之外,我还没有测试过它的速度。
      • 差点忘了回复这个,克雷格。谢谢你的主意。我会在某个时候看到有关对此进行测试的信息。就目前而言,我已经拥有的东西似乎已经足够好用了,所以我犹豫要不要改变任何东西;)
      • 哦,拜托,可能出了什么问题?距离远足季节真正开始还有 4 个月的时间 ;)
      【解决方案4】:

      您可以通过创建自定义MKTileOverlay 子类来避免它,如下所示:

      @interface MyTileOverlay : MKTileOverlay
      @end
      
      @implementation MyTileOverlay
      
      - (NSURL *)URLForTilePath:(MKTileOverlayPath)path 
      {
          NSString *tileKey = [[NSString alloc] initWithFormat:@"%d%d%d", path.x, path.y, path.z];
          NSString *tilePath = [[NSBundle mainBundle] pathForResource:tileKey ofType:nil inDirectory:@"TileFolder"];
      
          NSURL *url;
          if (tilePath) 
          {
              url = [NSURL fileURLWithPath:tilePath];
          }
      
          return url;
      }
      
      - (void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData *, NSError *))result
      {
          NSURL *url = [self URLForTilePath:path];
          if (url)
          {
              [super loadTileAtPath:path result:result];
          }
      }
      
      @end
      

      如果您确定该图块不存在,则不要触发该图块加载。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 2015-05-15
        • 1970-01-01
        • 2021-05-27
        • 2012-08-25
        • 2019-07-04
        相关资源
        最近更新 更多