iOS / MKTileOverlay 和 PINCache 库的 MapKit 缓存管理问题
iOS / MapKit cache management issue with MKTileOverlay and PINCache library
我正在使用 MapKit,以便通过在 mapView 上添加 MKTileOverlay 来创建卫星和雷达动画。
使用 UISlider 和 PlayButton,我可以通过播放 MKOverlayRenderer 的 alpha(根据滑块的位置将它们设置为 0 或 0.75)来创建动画,例如 GIF。
动画非常流畅,我所有的卫星和雷达图块都在 mapView 上正确加载。
我遇到了一个缓存管理问题。
我意识到 MapKit 没有为我的 tileOverlay 使用缓存,这就是为什么我使用库 PINCache 来保存我的图块,这样它就不会在我每次播放动画时请求和下载图像。
我的实现:
我覆盖方法 URLForTilePath
以构建我的 URL 来获取我的平铺图像。
- (NSURL *)URLForTilePath:(MKTileOverlayPath)path{
double latMin, latMax, longMin, longMax;
path.contentScaleFactor = 1.0;
NSMutableArray *result = [[NSMutableArray alloc] init];
result = getBBoxForCoordinates((int)path.x, (int)path.y, (int)path.z);
longMin = [[result objectAtIndex:0] doubleValue];
latMin = [[result objectAtIndex:1] doubleValue];
longMax = [[result objectAtIndex:2] doubleValue];
latMax = [[result objectAtIndex:3] doubleValue];
NSString *finalURL = self.url;
finalURL = [finalURL stringByReplacingOccurrencesOfString:@"DATE"
withString:_date];
NSString *bbox = [NSString stringWithFormat:@"bbox=%f,%f,%f,%f", longMin, latMin, longMax, latMax];
finalURL = [finalURL stringByReplacingOccurrencesOfString:@"BBOX"
withString:bbox];
return [NSURL URLWithString:finalURL];
}
调用 URLForTilePath
的关键方法是我对 loadTileAtPath
的实现:
- (void)loadTileAtPath:(MKTileOverlayPath)path
result:(void (^)(NSData *data, NSError *error))result
{
if (!result)
{
return;
}
NSString *str = self.isRadar == true ? [NSString stringWithFormat:@"Radar%@", self.date] : [NSString stringWithFormat:@"Satellite%@", self.date];
NSData *cachedData = [[PINCache sharedCache] objectForKey:str];
if (cachedData)
{
result(cachedData, nil);
}
else
{
NSURLRequest *request = [NSURLRequest requestWithURL:[self URLForTilePath:path]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSString *str = self.isRadar == true ? [NSString stringWithFormat:@"Radar%@", self.date] : [NSString stringWithFormat:@"Satellite%@", self.date];
[[PINCache sharedCache] setObject:data forKey:str block:nil];
result(data, connectionError);
}];
}
}
基本上我想要实现的是:
- 检查我是否有缓存数据,如果有则获取对象。
- 如果没有,我请求下载
URLForTilePath
给出的 URL 的磁贴。
- 然后我将对象设置为缓存。
- 字符串
str
是我缓存管理的Key
- 我有 2 个重要的值来排序和区分图块、类型(雷达或卫星、不同的图像、不同的 URL)和日期。
我可以看到缓存管理正在运行,Overlays 渲染速度更快,但我遇到的主要问题是它不会在相应的坐标处加载和构建图块。
我的 mapView 就像一个拼错世界的拼图。
用我的代码,你能看出我做错了什么吗?
我找不到这个 memory/cache mapKit 管理问题的原因。
我决定尝试使用 GoogleMap,我只用了不到 2 个小时就实现了它,结果令人惊叹。
我想通过使用 Apple 解决方案来尊重 Apple 社区,但是 Google Map 为我提供了更多性能。
我正在使用 MapKit,以便通过在 mapView 上添加 MKTileOverlay 来创建卫星和雷达动画。
使用 UISlider 和 PlayButton,我可以通过播放 MKOverlayRenderer 的 alpha(根据滑块的位置将它们设置为 0 或 0.75)来创建动画,例如 GIF。
动画非常流畅,我所有的卫星和雷达图块都在 mapView 上正确加载。
我遇到了一个缓存管理问题。
我意识到 MapKit 没有为我的 tileOverlay 使用缓存,这就是为什么我使用库 PINCache 来保存我的图块,这样它就不会在我每次播放动画时请求和下载图像。
我的实现:
我覆盖方法 URLForTilePath
以构建我的 URL 来获取我的平铺图像。
- (NSURL *)URLForTilePath:(MKTileOverlayPath)path{
double latMin, latMax, longMin, longMax;
path.contentScaleFactor = 1.0;
NSMutableArray *result = [[NSMutableArray alloc] init];
result = getBBoxForCoordinates((int)path.x, (int)path.y, (int)path.z);
longMin = [[result objectAtIndex:0] doubleValue];
latMin = [[result objectAtIndex:1] doubleValue];
longMax = [[result objectAtIndex:2] doubleValue];
latMax = [[result objectAtIndex:3] doubleValue];
NSString *finalURL = self.url;
finalURL = [finalURL stringByReplacingOccurrencesOfString:@"DATE"
withString:_date];
NSString *bbox = [NSString stringWithFormat:@"bbox=%f,%f,%f,%f", longMin, latMin, longMax, latMax];
finalURL = [finalURL stringByReplacingOccurrencesOfString:@"BBOX"
withString:bbox];
return [NSURL URLWithString:finalURL];
}
调用 URLForTilePath
的关键方法是我对 loadTileAtPath
的实现:
- (void)loadTileAtPath:(MKTileOverlayPath)path
result:(void (^)(NSData *data, NSError *error))result
{
if (!result)
{
return;
}
NSString *str = self.isRadar == true ? [NSString stringWithFormat:@"Radar%@", self.date] : [NSString stringWithFormat:@"Satellite%@", self.date];
NSData *cachedData = [[PINCache sharedCache] objectForKey:str];
if (cachedData)
{
result(cachedData, nil);
}
else
{
NSURLRequest *request = [NSURLRequest requestWithURL:[self URLForTilePath:path]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSString *str = self.isRadar == true ? [NSString stringWithFormat:@"Radar%@", self.date] : [NSString stringWithFormat:@"Satellite%@", self.date];
[[PINCache sharedCache] setObject:data forKey:str block:nil];
result(data, connectionError);
}];
}
}
基本上我想要实现的是:
- 检查我是否有缓存数据,如果有则获取对象。
- 如果没有,我请求下载
URLForTilePath
给出的 URL 的磁贴。 - 然后我将对象设置为缓存。
- 字符串
str
是我缓存管理的Key - 我有 2 个重要的值来排序和区分图块、类型(雷达或卫星、不同的图像、不同的 URL)和日期。
我可以看到缓存管理正在运行,Overlays 渲染速度更快,但我遇到的主要问题是它不会在相应的坐标处加载和构建图块。
我的 mapView 就像一个拼错世界的拼图。
用我的代码,你能看出我做错了什么吗?
我找不到这个 memory/cache mapKit 管理问题的原因。
我决定尝试使用 GoogleMap,我只用了不到 2 个小时就实现了它,结果令人惊叹。
我想通过使用 Apple 解决方案来尊重 Apple 社区,但是 Google Map 为我提供了更多性能。