ios 高德地图加载瓦片地图_iOS高德地图添加自定义瓦片地图
瓦片地圖
首先解釋一下什么是瓦片地圖,我們使用的地圖(例如百度,高德)都有一個底圖,在每一級的縮放比例下,都有一張很大的底圖,這張底圖按固定的大小切割成若干份,在地圖顯示時根據顯示范圍和縮放比例,請求對應幾張小的底圖,這些底圖就是瓦片地圖。
項目需求
項目使用的是高德地圖,基本的操作可以參考官方文檔,然后需要疊加自己的瓦片地圖。在官方文檔中找了好久,終于在繪制面_繪制瓦片圖層這一節中找到了相應的方法。主要步驟是先添加一個MATileOverlay到地圖中,然后實現delegate中的mapView:viewForOverlay:函數,返回一個renderer對象。項目中用到的所有地圖都要加載這個瓦片服務,所以直接從MAMapView繼承出一個自定義MapView。
代碼實現
自定義一個PPGMapView,繼承自MAMapView。
#import NS_ASSUME_NONNULL_BEGIN
@interface PPGMapView : MAMapView
@end
NS_ASSUME_NONNULL_END
在初始化時添加自定義瓦片圖層。
- (void)commonInit {
// delegate指向自己
self.delegate = self;
// 初始化縮放級別
self.zoomLevel = 18.f;
self.showsUserLocation = YES;
self.userTrackingMode = MAUserTrackingModeFollow;
// 添加自定義瓦片圖層
PPGTileOverlay *overlay = [[PPGTileOverlay alloc] init];
overlay.maximumZ = 20;
overlay.minimumZ = 14;
overlay.boundingMapRect = MAMapRectWorld;
[self addOverlay:overlay];
}
實現renderer方法
- (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id )overlay {
// 外部delegate首先進行響應,如果沒有實現,則使用自定義地圖的實現
if ([self.extDelegate respondsToSelector:_cmd]) {
MAOverlayRenderer *renderer = [self.extDelegate mapView:mapView rendererForOverlay:overlay];
if (renderer) {
return renderer;
}
}
if ([overlay isKindOfClass:[MATileOverlay class]]) {
// 默認的瓦片底圖renderer
MATileOverlayRenderer *renderer = [[MATileOverlayRenderer alloc] initWithTileOverlay:overlay];
return renderer;
}
return nil;
}
下面是自定義瓦片地圖的代碼
/**
自定義瓦片圖層,繼承自MATileOverlay
*/
@interface PPGTileOverlay : MATileOverlay
@end
@implementation PPGTileOverlay
- (NSURL *)URLForTilePath:(MATileOverlayPath)path {
#warning 自行替換ip和端口號
NSString *urlStr = [NSString stringWithFormat:@"http://ip:port/mapImg/tiles/%ld/%ld_%ld.png", (long)path.z, (long)path.x, (long)path.y];
return [NSURL URLWithString:urlStr];
}
// 使用template和上面的方法會丟掉端口號,所以自己去請求,然后回調結果
- (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *, NSError *))result {
NSURL *url = [self URLForTilePath:path];
// 使用SDWebImage管理本地瓦片
SDImageCache *cache = [SDImageCache sharedImageCache];
UIImage *image = [cache imageFromCacheForKey:[url absoluteString]];
if (image) {
result(UIImagePNGRepresentation(image), nil);
} else {
// 在3D地圖中如果瓦片請求失敗,會一直重復去請求,這里用set存儲已請求的瓦片,不做重復請求
static NSMutableSet *urlSet;
if (urlSet == nil) {
urlSet = [NSMutableSet new];
}
if ([urlSet containsObject:url]) {
return;
}
[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:url options:SDWebImageDownloaderHighPriority progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
if (finished && data) {
[cache storeImageDataToDisk:data forKey:[url absoluteString]];
}
result(data, error);
[urlSet addObject:url];
}];
}
}
@end
到這里瓦片地圖就添加上去了,這里還有一個delegate的問題,因為我們初始化的時候設置delegate為自己了,瓦片地圖才能正常顯示,如果這是在使用的時候delegate設置為另外一個對象,而他沒實現上面的renderer 方法,那么我們的瓦片地圖又不能顯示了,所以這里使用了外部delegate方法。
在自定義MapView中添加一個Extension,添加私有屬性extDelegate
@interface PPGMapView () /**
外部的代理
*/
@property (nonatomic, weak) idextDelegate;
@end
重寫setDelegate方法和respondsToSelector方法
// 保存本地delegate,記錄外部delegate
- (void)setDelegate:(id)delegate {
if (delegate == self) {
[super setDelegate:delegate];
} else {
self.extDelegate = delegate;
}
}
- (BOOL)respondsToSelector:(SEL)aSelector {
BOOL responds = [super respondsToSelector:aSelector];
if (responds) {
return responds;
} else {
return [self.extDelegate respondsToSelector:aSelector];
}
}
runtime轉發方法到外部delegate
// runtime消息轉發
- (id)forwardingTargetForSelector:(SEL)aSelector {
if ([self.extDelegate respondsToSelector:aSelector]) {
return self.extDelegate;
}
return nil;
}
代碼倉庫地址:
https://github.com/gaopeng-hz/TileOverlay
總結
以上是生活随笔為你收集整理的ios 高德地图加载瓦片地图_iOS高德地图添加自定义瓦片地图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从零开始之驱动发开、linux驱动(二十
- 下一篇: Flash 计时器