Demo:  https://github.com/xushiyou23/AMapTesting

转:

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Bear_861110453/article/details/81564605
 
本文主要介绍通过自定义高德地图 MATileOverlay 接口,添加 WMS 服务到地图上。

自定义类 WMSTileOverlayUtil,继承自高德地图接口 MATileOverlay,主要重载函数: 
- (NSURL *)URLForTilePath:(MATileOverlayPath)path; 
- (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result;,见代码注释。

#import <Foundation/Foundation.h>
#import <MAMapKit/MATileOverlay.h> @interface WMSTileOverlayUtil : MATileOverlay - (id)initWithRootURL:(NSString *)rootRUL; /**
* @brief 以tile path生成URL。用于加载tile,此方法默认填充URLTemplate
* @param path tile path
* @return 以tile path生成tileOverlay
*/
- (NSURL *)URLForTilePath:(MATileOverlayPath)path; @end
#import "WMSTileOverlayUtil.h"
#import <MAMapKit/MAMapKit.h>
#import <AMapFoundationKit/AMapFoundationKit.h>
#import <math.h> #import "Api.h" @implementation WMSTileOverlayUtil
{
NSString * rootURL;
NSInteger titleSize; // = 256
double initialResolution; // = 156543.03392804062;//2*Math.PI*6378137/titleSize;
double originShift; // = 20037508.342789244;//2*Math.PI*6378137/2.0; 周长的一半
double HALF_PI; // = Math.PI / 2.0;
double RAD_PER_DEGREE; // = Math.PI / 180.0;
double METER_PER_DEGREE; // = originShift / 180.0;//一度多少米
double DEGREE_PER_METER; // = 180.0 / originShift;//一米多少度
} - (id)initWithRootURL:(NSString *)rootRUL {
self = [super init];
if (self) {
rootURL = rootRUL;
titleSize = 256;
initialResolution = 156543.03392804062;
originShift = 20037508.342789244;
HALF_PI = M_PI_2;
RAD_PER_DEGREE = M_PI / 180.0;
METER_PER_DEGREE = originShift / 180.0;
DEGREE_PER_METER = 180.0 / originShift;
}
return self;
} /**
* @brief 以tile path生成URL。用于加载tile,此方法默认填充URLTemplate
* @param path tile path
* @return 以tile path生成tileOverlay
*/
- (NSURL *)URLForTilePath:(MATileOverlayPath)path {
NSString * strURL = [[NSString alloc] initWithFormat:@"%@%@", rootURL, [self titleBoundsByX:path.x
Y:path.y
Z:path.z]];
NSURL * url = [NSURL URLWithString:strURL];
return url;
} /**
* @brief 加载被请求的tile,并以tile数据或加载tile失败error访问回调block;默认实现为首先用URLForTilePath去获取URL,然后用异步NSURLConnection加载tile
* @param path tile path
* @param result 用来传入tile数据或加载tile失败的error访问的回调block
*/
- (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result {
if (path.z < 8) return;
NSURL * url = [self URLForTilePath:path];
NSString * strURL = url.absoluteString; SuccessCallback successCallback = ^(id responseObject) {
UIImage * image = [UIImage imageWithData:responseObject];
NSData * data = UIImagePNGRepresentation(image);
result(data, nil);
}; FailureCallBack failureCallBack = ^(NSError *error) {
result(nil, error);
}; [Api GETWMSWith:strURL successCallback:successCallback failureCallBack:failureCallBack];
} /**
* @brief 取消请求瓦片,当地图显示区域发生变化时,会取消显示区域外的瓦片的下载, 当disableOffScreenTileLoading=YES时会被调用。since 5.3.0
* @param path tile path
*/
- (void)cancelLoadOfTileAtPath:(MATileOverlayPath)path {
[super cancelLoadOfTileAtPath:path];
} /**
* 根据瓦片的x/y等级返回瓦片范围
*
* @param tx x
* @param ty y
* @param zoom z
* @return url
*/
- (NSString *)titleBoundsByX:(NSInteger)tx Y:(NSInteger)ty Z:(NSInteger)zoom {
double minX = [self pixels2Meters:(tx * titleSize) zoom:zoom];
double maxY = -[self pixels2Meters:(ty * titleSize) zoom:zoom];
double maxX = [self pixels2Meters:((tx + 1) * titleSize) zoom:zoom];
double minY = -[self pixels2Meters:((ty + 1) * titleSize) zoom:zoom]; //转换成经纬度
minX = [self meters2Lon:minX];
minY = [self meters2Lat:minY];
maxX = [self meters2Lon:maxX];
maxY = [self meters2Lat:maxY];
//坐标转换工具类构造方法 Gps( WGS-84) 转 为高德地图需要的坐标
CLLocationCoordinate2D amapcoord = AMapCoordinateConvert(CLLocationCoordinate2DMake(minY, minX), AMapCoordinateTypeGPS);
minY = amapcoord.latitude;
minX = amapcoord.longitude; CLLocationCoordinate2D maxAmapcoord = AMapCoordinateConvert(CLLocationCoordinate2DMake(maxY, maxX), AMapCoordinateTypeGPS);
maxY = maxAmapcoord.latitude;
maxX = maxAmapcoord.longitude;
NSString * result = [[NSString alloc] initWithFormat:@"%f,%f,%f,%f&width=256&height=256", minX, minY, maxX, maxY];
return result;
} /**
* 根据像素、等级算出坐标
*
* @param p p
* @param zoom z
* @return double
*/
- (double)pixels2Meters:(NSInteger)p zoom:(NSInteger)zoom {
return p * [self resolution:zoom] - originShift;
} /**
* 计算分辨率
*
* @param zoom z
* @return double
*/
- (double)resolution:(NSInteger)zoom {
return initialResolution / (pow(2, zoom));
} /**
* X米转经纬度
*/
- (double)meters2Lon:(double)mx {
double lon = mx * DEGREE_PER_METER;
return lon;
} /**
* Y米转经纬度
*/
- (double)meters2Lat:(double)my {
double lat = my * DEGREE_PER_METER;
lat = 180.0 / M_PI * (2 * atan(exp(lat * RAD_PER_DEGREE)) - HALF_PI);
return lat;
} @end

其中,- (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result; 函数中,使用自己写的 网络访问层去请求 wms 服务,并通过 result 函数贴到地图上。你也可以 改写成自己的网络访问层。

问题

为啥要重载 - (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result; 函数,因为只是从载 - (NSURL *)URLForTilePath:(MATileOverlayPath)path; 生成 NSURL 后,loadTileAtPath 函数会去通过网络请求加载 wms 服务,然而,这一步网络请求会报错:NSURLConnection -errorcode -1004,且一个星期没有解决为啥报错,所以只得重写,如果有熟悉高德地图 api 的小伙伴能够给予解答,不胜感激。

注意

如果使用 AFNetworking 要注意修改支持的类型:

 AFHTTPSessionManager * manager = [[AFHTTPSessionManager alloc] init];
AFHTTPResponseSerializer *serializer=[AFHTTPResponseSerializer serializer];
serializer.acceptableContentTypes = [NSSet setWithObject:@"image/png"];
manager.responseSerializer = serializer;

iOS 利用高德地图WMS服务的更多相关文章

  1. 高德地图-搜索服务-POI搜索

    高德地图-搜索服务-POI搜索 之前公司项目收货地址仿饿了么的收货地址,结果发现自己实现的关键字搜索和周边搜索,搜索到的poi列表跟饿了么的并不完全一样,后来考虑了下,应该是搜索的范围.类型之类的设置 ...

  2. 利用高德地图javascriptAPI做一个自己的地图

    最近由于项目中需要制作一个地图,用来选择活动地点,我就花了两天利用高德地图的javascriptAPI自制了一个地图的demo.在这了记录一下我学习的过程. 一.进入高德地图官网,再找到高德地图的开放 ...

  3. 【视频教学】如何利用高德地图IOS SDK进行开发?

    Step1:使用IOS SDK可以做什么高德地图 iOS SDK 是一套基于 iOS 5.1.1 及以上版本的地图应用程序开发接口.通过该接口,用户可使用高德地图数据和服务轻松构建功能丰富.交互性强的 ...

  4. iOS导入高德地图出现缺失armv7--"Undefined symbols for architecture armv7"

    在已有项目中使用pod导入高德地图,报了以下错误: ld: warning: directory not found for option '-L/Users/paul/iOS/yun-hui-yi/ ...

  5. iOS的高德地图标注特定位置

    在开发时有时候遇到项目里面需要展示公司的位置,这时如果导入百度地图什么的就太浪费资源,而且还占内存 这时只要调用自动高德地图的就行了 自己写一个控制器,导入框架 现在导入系统框架只要多打次就能出来了, ...

  6. iOS 去除高德地图下方的 logo 图标

    [self.mapView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, ...

  7. 安卓开发笔记①:利用高德地图API进行定位、开发电子围栏、天气预报、轨迹记录、搜索周边(位置)

    高德地图开发时需要导入的包在下面的网盘链接中:(由于高德地图api更新得太快,官网上最新的包使用起来没有之前的方便,所以以下提供最全面的原始包) 链接:http://pan.baidu.com/s/1 ...

  8. android开发对应高德地图定位服务进度一

    进行android的高德地图开发首先需要进入高德地图的控制台进行注册登录.之后创建新的应用并且绑定软件得到相应的key. 这里面需要找到自己软件对应的多个SHA1.这里有发布版和调试版,以及对应的软件 ...

  9. ios开发--高德地图SDK使用简介

    高德LBS开放平台将高德最专业的定位.地图.搜索.导航等能力,以API.SDK等形式向广大开发者免费开放.本章节我们来简单学习一下如何使用它的定位及地图SDK. 一.相关框架及环境配置 地图SDK 对 ...

随机推荐

  1. 后端开发者的Vue学习之路(二)

    目录 上篇内容回顾: 数据绑定 表单输入框绑定 单行文本输入框 多行文本输入框 复选框checkbox 单选框radio 选择框select 数据绑定的修饰符 .lazy .number .trim ...

  2. 解读《德勤2017年全球CIO报告》:顶级CIO的炼成之道

    文|水手 日前,德勤发布了<2016-2017年全球CIO调查报告>.在这份报告中,德勤从影响CIO为企业创造价值的能力的决定因素出发,探索了CIO为企业进行价值创造的方式,同时以CIO的 ...

  3. MongoDB的存储结构及对空间使用率的影响

    MongoDB的存储结构及对空间使用率的影响 使用MongoDB一段时间的同学肯定会发现,MongoDB往往会占用比实际数据大小多不少空间的问题.如果利用db.stats()命令去查看,会发现Mong ...

  4. PJSUA2开发文档--第三章 PJSUA2高级API

    3. PJSUA2高级API PJSUA2是PJSUA API以上的面向对象抽象.它为构建会话发起协议(SIP)多媒体用户代理应用程序(也称为IP / VoIP软电话)提供高级API.它将信令,媒体和 ...

  5. 使用VsCode自带的Emmet语法

    新建html文件,保存之后,输入"!",按Tap(或Enter)键,自动生成HTML结构 标签只要直接输入标签名(不要输入<>),按Tap(或Enter)键自动生成完整 ...

  6. 【腾讯云服务器】基于centos7搭建ftp服务器(vsftpd)

    该博客分为三部分设置,1.ftp服务器搭建.2.防火墙设置  3.腾讯云安全组 一.ftp服务器搭建 1.1  安装vsftpd yum install vsftpd -y 1.2 启动vsftpd服 ...

  7. 高端内存映射之kmap_atomic固定映射--Linux内存管理(二十一)

    1 固定映射 1.1 数据结构 linux高端内存中的临时内存区为固定内存区的一部分, 对于固定内存在linux内核中有下面描述 x86 arm arm64 arch/x86/include/asm/ ...

  8. c/c++ llinux epoll系列4 利用epoll_wait实现非阻塞的connect

    llinux epoll系列4 利用epoll_wait实现非阻塞的connect connect函数是阻塞的,而且不能设置connect函数的timeout时间,所以一旦阻塞太长时间,影响用户的体验 ...

  9. iOS transform属性的使用

    1.transform属性 在iOS开发中,通过transform属性可以修改UIView对象的平移.缩放比例和旋转角度,常用的创建transform结构体方法分两大类 (1) 创建“基于控件初始位置 ...

  10. Java - String 的字面量、常量池、构造函数和intern()函数

    一.内存中的 String 对象 Java 的堆和栈 对于基本数据类型变量和对象的引用,也就是局部变量表属于栈内存: 而通过 new 关键字和 constructor 创建的对象存放在堆内存: 直接的 ...