代码之家  ›  专栏  ›  技术社区  ›  Tj3n

iOS 13.2 MKTileOverlay偶尔不会渲染

  •  0
  • Tj3n  · 技术社区  · 6 年前

    我遇到了一个问题,在iOS 13.2中(可能也来自iOS 13),使用 MKTileOverlay 有时将无法渲染,将平铺留空,似乎没有问题 MKTileOverlay 的子类,因为它在iOS 12及以下版本中运行良好。我有两个 MKTileOverlay MKTileOverlay MKTileOverlayRenderer ,其他覆盖层看起来很好。

    如果我转到主屏幕并返回应用程序,导致磁砖重新加载,问题似乎会自行解决。这是iOS MapKit本身的bug吗?有人对此有临时解决办法吗?非常感谢。

    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

    0 回复  |  直到 6 年前
        1
  •  2
  •   Phil John    6 年前

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

    我的问题发生在以下方法中

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

    我发现,如果我使用JPEG而不是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)
            {
    
            }
        }
    
        2
  •  2
  •   Denis    6 年前

    这显然是一个MapKit问题/bug。

    自2020年12月9日起,我还打开了一张反馈单。

    这个问题的根源还不是很清楚。

    因此,由于JPEG平铺通常比PNG更轻,因此JPEG可以作为一种解决方法。

    但是 ,这个新的iOS 13.2+版本不一样!不渲染随机平铺。如果删除并读取MKTileOverlay或调用MKTileOverlayRenderer的reloadData方法,则丢失的分片将被渲染,并将被删除

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

    编辑 :我刚刚试着用85%的JPEG替换我的8位PNG,这个非常简单的MKTileOverlay项目示例是我在我的票证中发给苹果的。同样的问题。。。没有改善。

    编辑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);
        });
    }