APP开发需求:加载地图,定位到用户当前的位置,并标注附近的坐标点(上图中的蓝色标注点)。坐标数据由业务人员提供。同时还需要将用户地理位置(城市)上传到服务端。地图sdk选择高德家的,高德地图对开发者比较友好。首先,注册高德开发者账号,注册之后登录帐号,申请用户Key。
开发环境配置
高德提供CocoaPods安装方式,这点比百度地图做的好。自动安装比手动安装方便太多了。在Podfile中添加下面两行
pod 'AMap2DMap'
pod 'AMapSearch' #搜索服务SDK
运行命令pod install
安装高德sdk。更详细的步骤移步高德开发者配置文档。
地图功能
首先,引入头文件
#import <AMapSearchKit/AMapSearchKit.h>
#import <MAMapKit/MAMapKit.h>
初始化mapview
self.mapView = [[MAMapView alloc] initWithFrame:self.view.bounds];
self.mapView.delegate = self;
self.mapView.showsUserLocation = YES; //YES 为打开定位,NO为关闭定位
self.mapView.showsCompass = NO;
self.mapView.showsScale = NO;
self.mapView.userTrackingMode = MAUserTrackingModeFollow; // 追踪用户地理位置更新
self.mapView.zoomLevel = 16.1;
self.mapView.alpha = 0.8;
实现 MAMapViewDelegate,获取用户当前经纬坐标:
#pragma mark - MAMapViewDelegate
-(void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation{
if(updatingLocation){
//取出当前位置的坐标
self.currentCoordinate = userLocation.coordinate;
}
}
- (void)mapView:(MAMapView *)mapView didFailToLocateUserWithError:(NSError *)error {
DLog(@"%@",error);
}
当用户手动滑动地图后,可点击界面上的定位按钮,将地图中心定位到用户当前位置
-(void)locationButtonClicked {
if (self.currentCoordinate.latitude > 0) {
CLLocationCoordinate2D myCoordinate = self.currentCoordinate;
MACoordinateRegion theRegion = MACoordinateRegionMake(myCoordinate, MACoordinateSpanMake(0.2, 0.2));
[self.mapView setScrollEnabled:YES];
[self.mapView setRegion:theRegion animated:YES];
[self.mapView setZoomLevel:16.1 animated:NO];
}
}
通过地理位置经纬坐标获取城市名称,即逆地理编码
逆地理编码,又称地址解析服务,是指从已知的经纬度坐标到对应的地址描述(如行政区划、街区、楼层、房间等)的转换。常用于根据定位的坐标来获取该地点的位置详细信息,与定位功能是黄金搭档。
进行逆地编码时,请求参数类为 AMapReGeocodeSearchRequest,location为必设参数。
- (void)searchLocationWithCoordinate2D:(CLLocationCoordinate2D )coordinate {
//构造AMapReGeocodeSearchRequest对象
AMapReGeocodeSearchRequest *regeo = [[AMapReGeocodeSearchRequest alloc] init];
regeo.location = [AMapGeoPoint locationWithLatitude:coordinate.latitude longitude:coordinate.longitude];
regeo.radius = 10000;
regeo.requireExtension = YES;
//发起逆地理编码
[self.searchAPI AMapReGoecodeSearch: regeo];
}
实现逆地理编码的回调函数
#pragma mark - AMapSearchDelegate
- (void)onReGeocodeSearchDone:(AMapReGeocodeSearchRequest *)request response:(AMapReGeocodeSearchResponse *)response
{
if(response.regeocode != nil)
{
//通过AMapReGeocodeSearchResponse对象处理搜索结果
NSString *city = response.regeocode.addressComponent.city;
if (!city || [city length] == 0) {
city = response.regeocode.addressComponent.province; // 直辖市时获取此字段
}
self.city = city;
}
}
云检索
开发检索自有数据的步骤:
第一步,数据存储。开发者需要将待检索数据存入云图,并对要检索的字段建立索引管理。
第二步,检索。利用SDK为开发者提供的接口检索自己的数据。
第三步,展示。开发者可根据自己的实际需求以多种形式(如结果列表、地图模式等)展现自己的数据。
1.数据存储
由于要导入的数据量比较多,可以调用云图API批量上传数据。利用API创建云图表,需先申请Web服务APIkey,此key和ios端的key是两个独立的key,这个key用于webapi调用。创建表:
> $apikey=xxxxxxxx;
> curl -d "key=$apikey&name=test" http://yuntuapi.amap.com/datamanage/table/create
status=1表明创建成功,同时返回的还有tableid,根据这个tableid就可以做数据导入
{"info":"OK","status":1,"tableid":"565c0fa8e4b0dce2a8eabc81"}%
批量上传数据只能以文件的形式:
向指定tableid的数据表中通过上传文件的方式创建多条数据。该接口为异步接口,请求后立即返回后台进程batchid,通过批量创建数据进度查询接口查看任务执行进度和结果。
文件格式和大小有限制:
- csv文件的二进制流,使用UTF8、GBK编码
- 数据量不超过10000条且文件大小不超过10M
- 字段总数不超过40个。
- 字段命名规则:以英文字母开头,仅由英文字母、数字、下划线组成,总长度不超过20位
文件内容如下,name,address,longitude,latitude这四个字段是必须的,可以自定义其他字段。
name,address,longitude,latitude
543691,北京市东城区故宫博物院,116.312361,39.843083
543692,北京海淀区中关村大街1号海龙大厦,116.365686,40.034993
上传脚本:
#!/bin/bash
key=xxxxxxx
tableid=565c0fa8e4b0dce2a8eabc81
uploadDir=/User/upload
for i in `cat uploadfile.txt` #uploadfile.txt包含了所有要上传的文件名称
do
echo -n "$i "
curl -F "file=@$uploadDir/$i" http://yuntuapi.amap.com/datamanage/data/batchcreate\\\\?key\\\\=$key\\\\&tableid\\\\=$tableid\\\\&_name\\\\=name\\\\&loctype\\\\=2\\\\&_address\\\\=address\\\\&longitude\\\\=longitude\\\\&latitude\\\\=latitude
echo " "
sleep 60
done
注意sleep 60
,没有这个的话,可能无法上传成功,至少我没加sleep就全部请求返回失败。
2.客户端检索和展示:
这里需要实现的是周边检索,周边检索的请求参数对象为 AMapCloudPOIAroundSearchRequest ,其中:center 参数为必填参数。
- (void)searchCloudMapWithCenterLocationCoordinate2D:(CLLocationCoordinate2D )coordinate {
NSString *tableID = self.tableID // 云图的tableID
AMapCloudPOIAroundSearchRequest *request = [[AMapCloudPOIAroundSearchRequest alloc] init];
request.tableID = tableID;
request.center = [AMapGeoPoint locationWithLatitude:coordinate.latitude longitude:coordinate.longitude];
request.radius = 100000;
request.offset = 100; // 最多只能获取100条数据
request.page = 1; // 第一页
[self.searchAPI AMapCloudPOIAroundSearch:request];
}
//实现云检索对应的回调函数,添加标注Annotation
#pragma mark - AMapSearchDelegate
- (void)onCloudSearchDone:(AMapCloudSearchBaseRequest *)request response:(AMapCloudPOISearchResponse *)response {
NSMutableArray *annotations = [[NSMutableArray alloc] init];
for (AMapCloudPOI *poi in response.POIs) {
AMapGeoPoint *point = poi.location;
MAPointAnnotation *annotation = [[MAPointAnnotation alloc] init];
annotation.coordinate = CLLocationCoordinate2DMake(point.latitude, point.longitude);
[annotations addObject:a1];
}
[self.mapView addAnnotations:[annotations copy]];
[self.mapView showAnnotations:annotations animated:YES];
}
实现 MAMapViewDelegate 协议中的 mapView:viewForAnnotation:回调函数,设置标注样式。
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation
{
if ([annotation isKindOfClass:[MAPointAnnotation class]])
{
static NSString *pointReuseIndetifier = @"pointReuseIndetifier";
MAPinAnnotationView *annotationView = (MAPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndetifier];
if (annotationView == nil)
{
annotationView = [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndetifier];
annotationView.image = [UIImage imageNamed:@"location_annotation"];
}
return annotationView;
}
return nil;
}
地图定位加标注的功能就完成了。
网友评论
[self.mapView addAnnotations:self.dataScoure];
[self.mapView showAnnotations:self.dataScoure animated:YES];
这两个方法,我的界面是蓝屏的,请问您知道原因不?
//实现逆地理编码的回调函数
- (void)onReGeocodeSearchDone:(AMapReGeocodeSearchRequest *)request response:(AMapReGeocodeSearchResponse *)response
{
if(response.regeocode != nil)
{
//通过AMapReGeocodeSearchResponse对象处理搜索结果
AMapAddressComponent *address = response.regeocode.addressComponent;
NSString *township;
if (address.township != nil && [address.township length] > 0) {
township = [address.township stringByReplacingOccurrencesOfString:@"街道$" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [address.township length])];
} else {
township = @"";
}
NSString *locationString = [NSString stringWithFormat:@"您的位置:%@%@", address.district, township];
NSLog(@"%@",locationString);
}
}