iOS 13.2 MKTileOverlay有时不会渲染

时间:2019-12-30 03:31:06

标签: ios swift mapkit

我遇到一个问题,在iOS 13.2(可能也是从iOS 13)中,有时无法使用MKTileOverlay加载离线地图图块,将图块留空,似乎没有MKTileOverlay的子类根本没有问题,因为它在iOS 12及更低版本中运行良好。我有2个MKTileOverlay类(1个添加网格和1个加载地图图块文件,默认为MKTileOverlay),都无法使用默认的MKTileOverlayRenderer和其他叠加层加载到该空白图块上似乎很好。

如果我回到主屏幕并返回到应用程序,则问题似乎可以自行解决,从而导致重新加载磁贴。这是iOS MapKit本身的错误吗?有人对此有临时解决方案吗?谢谢。

添加叠加层的代码:

let overlay = MKTileOverlay(urlTemplate: urlTemplate)
overlay.canReplaceMapContent = true
overlay.maximumZ = 19
mapView.insertOverlay(overlay, at: 0, level: .aboveLabels)

渲染器:

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    if overlay is MKTileOverlay {
        let renderer = MKTileOverlayRenderer(tileOverlay: overlay as! MKTileOverlay)
        return renderer
    }

    return MKOverlayRenderer()
}

enter image description here

2 个答案:

答案 0 :(得分:2)

正如我在对原始问题的评论中指出的那样,我遇到了同样的问题,但是现在已经基本解决了,所以我认为我应该发布对我有用的东西。

我的问题出现在以下方法中

- (void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData * __nullable tileData, NSError * __nullable error))result{

自定义图块即使使用有效的NSData呈现时也无法加载。

我发现,如果我使用jpegs而不是png作为自定义图块,则该问题得到了缓解,但是只有当我改变了处理图块数据的方式时,问题才基本消失了。 (我主要是因为我偶尔还是会得到卸载的图块,但是我说它的使用频率比以前得到的要少100倍。)

以下方法是我的Xamarin.iOS实现,但是您应该能够了解Swift或Objective C的原理。

关键是创建NSData的方式不同。我没有调用UrlForTilePath方法,而是从切片路径创建了UIImage,然后使用UIImageJPEGRepresentation(在C#中为AsJPEG)创建NSData。

   public override void LoadTileAtPath(MKTileOverlayPath path, MKTileOverlayLoadTileCompletionHandler result)
    {
        //I was using this prior to ios 13.2

        //NSUrl url = this.URLForTilePath(path);
        //NSData tileData = NSData.FromFile(url.AbsoluteString);
        //result(tileData, null);

        //Now I use this

        String folderPath = "tiles/" + path.Z + "/" + path.X + "/";
        String tilePath = NSBundle.MainBundle.PathForResource(path.Y.ToString(), "jpg", folderPath);
        String blankPath = NSBundle.MainBundle.PathForResource("tile", "jpg");

        try
        {
            //does the file exist?
            UIImage tile;
            if (File.Exists(tilePath))
            {
                tile = UIImage.FromFile(tilePath);
                if (tile == null)
                {
                    Console.WriteLine("Error Loading " + path.Z + " " + path.Y + " " + path.X);
                    //This may be redundant, as I'm not getting any errors here, even when the tile doesn't display
                }
            }
            else
            {
                tile = UIImage.FromFile(blankPath);
            }

            NSData tileData = tile.AsJPEG();
            result(tileData, null);
        }
        catch (Exception ex)
        {

        }
    }

答案 1 :(得分:2)

这显然是MapKit的问题/错误。

自2020年12月9日起,我也开了反馈票。

这个问题的根源不是很确定。

MapKit尤其是MKTileOverlay始终对“重”图块(如PNG 24bit)存在某些问题。当MKTileOverlay使用PNG(沉重的图块)时,图块有时会闪烁,并且地图会不断地重新加载,尤其是在宽屏(iPad pro等)下。

因此,由于JPEG切片通常比PNG浅,因此JPEG可以解决。

,这个新的iOS 13.2+问题不一样!不渲染随机图块。如果您删除并读取了MKTileOverlay或调用了MKTileOverlayRenderer的reloadData方法,则丢失的图块将被呈现,并且将其他随机图块丢失的图块。

该问题的真正解决方案是打开反馈票证:https://feedbackassistant.apple.com

编辑:我刚刚尝试在机票中发送给Apple的非常简单的MKTileOverlay项目示例上,将8位PNG替换为85%JPEG。同样的问题...没有改善。

编辑2 :将NSData加载到UIImage中,然后使用UIImageRepresentationJPEG似乎可以解决问题……糟糕...

- (void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData * _Nullable, NSError * _Nullable))result
{
    NSString *tilePath = [self PATHForTilePath:path];
    NSData *data = nil;

    if (![[NSFileManager defaultManager] fileExistsAtPath:tilePath])
    {
        NSLog(@"Z%ld/%ld/%ld does not exist!", path.z, path.x, path.y);
    }
    else
    {
        NSLog(@"Z%ld/%ld/%ld exist", path.z, path.x, path.y);

        UIImage *image = [UIImage imageWithContentsOfFile:tilePath];
        data = UIImageJPEGRepresentation(image, 0.8);
        // Instead of: data = [NSData dataWithContentsOfFile:tilePath];

        if (data == nil)
        {
            NSLog(@"Error!!! Unable to read an existing file!");
        }
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        result(data, nil);
    });
}