我遇到一个问题,在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()
}
答案 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);
});
}