iOS 高德地图定位并进行周边搜索

  • Post author:
  • Post category:其他


项目需要实现仿微信朋友圈可定位、搜索附近位置的功能:


实现方法

第1步,集成SDK(这里使用 CocoaPods 安装)

pod 'AMapSearch' #地图SDK搜索功能
pod 'AMapLocation' #定位SDK

第2步,引入头文件

#import <AMapFoundationKit/AMapFoundationKit.h>
#import <AMapLocationKit/AMapLocationKit.h>
#import <AMapSearchKit/AMapSearchKit.h>

第3步,配置Key

在调用定位时,需要添加Key,需要注意的是请在 SDK 任何类的初始化以及方法调用之前设置正确的 Key。

[AMapServices sharedServices].apiKey = @"b5a84655e2cef54d488e990287d26bb9";

第4步,更改info.plist

在info.plist的字段添加定位权限的申请,配置方式请参考

手动部署

部分说明。

第5步,配置后台定位

第6步,代码实现

#import "SearchSitesController.h"

@interface SearchSitesController () <UITextFieldDelegate,AMapLocationManagerDelegate,AMapSearchDelegate>

@property (nonatomic,strong) UITextField *searchTxt;//搜索框

@property (nonatomic,assign) BOOL isSearchAround;

@property (nonatomic,strong) NSMutableArray *addressArray;//搜索到的地址数组

@property (nonatomic,strong) AMapLocationManager *locationManager;//定位管理

@property (nonatomic,strong) AMapSearchAPI *searchAPI;//搜索类

@property (nonatomic,strong) CLLocation *location;//当前定位的位置

@property (nonatomic,copy) NSString *currentCity;//当前城市

@end

@implementation SearchSitesController

#pragma mark - 懒加载

- (NSMutableArray *)addressArray
{
    if (!_addressArray) {
        _addressArray = [NSMutableArray array];
    }
    return _addressArray;
}

- (AMapLocationManager *)locationManager
{
    if (!_locationManager) {
        _locationManager = [[AMapLocationManager alloc] init];
        [_locationManager setDelegate:self];
        [_locationManager setAllowsBackgroundLocationUpdates:YES];
        //iOS 9(不包含iOS 9) 之前设置允许后台定位参数,保持不会被系统挂起
        [_locationManager setPausesLocationUpdatesAutomatically:NO];
        //iOS 9(包含iOS 9)之后新特性:将允许出现这种场景,同一app中多个locationmanager:一些只能在前台定位,另一些可在后台定位,并可随时禁止其后台定位。
        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
            _locationManager.allowsBackgroundLocationUpdates = YES;
        }
    }
    return _locationManager;
}

- (AMapSearchAPI *)searchAPI
{
    if (!_searchAPI) {
        _searchAPI = [[AMapSearchAPI alloc] init];
        _searchAPI.delegate = self;
    }
    return _searchAPI;
}



- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:nil style:UIBarButtonItemStylePlain target:nil action:nil];
   
    //搜索框
    _searchTxt = [HELPER textFieldWithSuperView:self.view textAlignment:NSTextAlignmentLeft fontSize:14 textColor:TITLE_BLACK backgroundColor:RGB(243, 244, 246) placeholder:@"搜索地点" placeholderColor:PLACEHOLDER_COLOR placeholderFont:14 andMasonryBlock:^(MASConstraintMaker * _Nonnull make) {
        make.left.equalTo(@11);
        make.right.equalTo(@-55);
        make.height.equalTo(@31);
        make.top.equalTo(@(10));
    }];
    _searchTxt.delegate = self;
    _searchTxt.layer.cornerRadius = 31/2;
    _searchTxt.layer.masksToBounds = YES;
    _searchTxt.clearButtonMode = UITextFieldViewModeWhileEditing;
    _searchTxt.leftView = [[UIView alloc]initWithFrame:FRAME(0, 0, 35, 35)];
    _searchTxt.leftViewMode = UITextFieldViewModeAlways;
    [HELPER imageViewWithSuperView:_searchTxt.leftView backgroundColor:COLOR(clearColor) image:IMG(@"icon_search") andMasonryBlock:^(MASConstraintMaker * _Nonnull make) {
        make.center.equalTo(self.searchTxt.leftView);
    }];
    [_searchTxt addTarget:self action:@selector(textFieldValueChanged:) forControlEvents:UIControlEventEditingChanged];
    
    //取消按钮
    [HELPER buttonWithSuperView:self.view andNormalTitle:@"取消" andNormalTextColor:PLACEHOLDER_COLOR andTextFont:16 andNormalImage:nil andCornerRadius:0 backgroundColor:COLOR(clearColor) addTarget:self action:@selector(cancelAction:) forControlEvents:UIControlEventTouchUpInside andMasonryBlock:^(MASConstraintMaker * _Nonnull make) {
        make.centerY.equalTo(self.searchTxt.mas_centerY);
        make.left.equalTo(self.searchTxt.mas_right).offset(5);
        make.right.equalTo(@-5);
    }];
    //分割线
    [HELPER imageViewWithSuperView:self.view backgroundColor:COLOR(groupTableViewBackgroundColor) image:nil andMasonryBlock:^(MASConstraintMaker * _Nonnull make) {
        make.height.equalTo(@1);
        make.left.right.equalTo(@0);
        make.top.equalTo(self.searchTxt.mas_bottom).offset(10);
    }];
    
    //设置tableView
    self.mainTableView = [self tableViewWithSuperView:self.view style:UITableViewStylePlain backgroundColor:COLOR(clearColor) target:self andMasonryBlock:^(MASConstraintMaker * _Nonnull make) {
        make.left.right.bottom.equalTo(@0);
        make.top.equalTo(self.searchTxt.mas_bottom).offset(11);
    }];
    self.mainTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
    self.mainTableView.separatorColor = COLOR(groupTableViewBackgroundColor);
  
    //开始定位
    [self.locationManager startUpdatingLocation];
}


#pragma mark - 点击取消按钮
- (void)cancelAction:(UIButton *)sender
{
    [self.navigationController popViewControllerAnimated:YES];
}


#pragma mark - AMapLocationManagerDelegate

/* 当定位发生错误时,会调用代理的此方法 */
- (void)amapLocationManager:(AMapLocationManager *)manager didFailWithError:(NSError *)error
{
    //定位错误
    LOG(@"定位❌error = %@",error);
}

/* 位置更新回调 */
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateLocation:(CLLocation *)location
{
    //经纬度
    LOG(@"location:{lat:%f; lon:%f}", location.coordinate.latitude, location.coordinate.longitude);
    
    self.location = location;
    
    //逆地理编码
    [self reGoecodeWithLocation:location];
    
    //发起周边搜索
    [self searchAroundWithKeywords:nil];
    
    //停止定位
    [self.locationManager stopUpdatingLocation];
}

//逆地理编码
- (void)reGoecodeWithLocation:(CLLocation *)location
{
    AMapReGeocodeSearchRequest *request = [[AMapReGeocodeSearchRequest alloc] init];
    request.location =[AMapGeoPoint locationWithLatitude:location.coordinate.latitude longitude:location.coordinate.longitude];
    [self.searchAPI AMapReGoecodeSearch:request];
}

//根据定位坐标或关键字进行周边搜索
- (void)searchAroundWithKeywords:(NSString *)keywords{
    if (keywords.length == 0) { //未输入关键字,则为POI周边搜索
        self.isSearchAround = YES;
        //构造AMapPOIAroundSearchRequest对象,设置周边搜索参数
        AMapPOIAroundSearchRequest *request = [[AMapPOIAroundSearchRequest alloc] init];
        request.location = [AMapGeoPoint locationWithLatitude:self.location.coordinate.latitude longitude:self.location.coordinate.longitude];
        //types属性表示限定搜索POI的类别,默认为:餐饮服务|商务住宅|生活服务
        //POI的类型共分为20种大类别
        request.types = @"汽车服务|汽车销售|汽车维修|摩托车服务|餐饮服务|购物服务|生活服务|体育休闲服务|医疗保健服务|住宿服务|风景名胜|商务住宅|政府机构及社会团体|科教文化服务|交通设施服务|金融保险服务|公司企业|道路附属设施|地名地址信息|公共设施";
        
        request.sortrule = 0;
        request.requireExtension = YES;
        //发起周边搜索请求
        [self.searchAPI AMapPOIAroundSearch:request];
    }else{ //输入了关键字,则为搜索提示请求
        self.isSearchAround = NO;
        AMapInputTipsSearchRequest *tipsRequest = [[AMapInputTipsSearchRequest alloc] init];
        tipsRequest.city = self.currentCity;//查询城市默认为当前定位的城市
        tipsRequest.keywords = keywords;
        [self.searchAPI AMapInputTipsSearch:tipsRequest];
    }
}


#pragma mark - AMapSearchDelegate

/* 逆地理编码查询回调函数 */
- (void)onReGeocodeSearchDone:(AMapReGeocodeSearchRequest *)request response:(AMapReGeocodeSearchResponse *)response
{
    self.currentCity = response.regeocode.addressComponent.city;
    if (self.currentCity.length == 0) {
        self.currentCity = response.regeocode.addressComponent.province;
    }
    LOG(@"当前定位城市 = %@",self.currentCity);
}

/* 实现POI搜索对应的回调函数 */
- (void)onPOISearchDone:(AMapPOISearchBaseRequest *)request response:(AMapPOISearchResponse *)response
{
    [self.addressArray removeAllObjects];
    if (response.pois.count>0) {
        //将搜索出的POI结果保存到数组
        [self.addressArray addObjectsFromArray:response.pois];
    }else{
        [self.mainTableView tableViewShowMessage:@"无结果" forDataCount:0];
    }
    [self.mainTableView reloadData];
}

/* 输入提示查询回调函数 */
- (void)onInputTipsSearchDone:(AMapInputTipsSearchRequest *)request response:(AMapInputTipsSearchResponse *)response
{
    [self.addressArray removeAllObjects];
    if (response.tips.count>0) {
        //将搜索出的结果保存到数组
        [self.addressArray addObjectsFromArray:response.tips];
    }else{
        [self.mainTableView tableViewShowMessage:@"无结果" forDataCount:0];
    }
    [self.mainTableView reloadData];
}


#pragma mark - <UITableViewDataSource,UITableViewDelegate>

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.addressArray.count;
}

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    NSString *identifier = @"cellID";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
    }
    if (self.isSearchAround == YES) {//POI周边搜索
        AMapPOI *poi = self.addressArray[indexPath.row];
        cell.textLabel.text = poi.name;
        cell.detailTextLabel.text = poi.address;
    }else{//输入提示搜索
        AMapTip *tip = self.addressArray[indexPath.row];
        cell.textLabel.text = tip.name;
        cell.detailTextLabel.text = tip.address;
    }
    return cell;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 50;
}

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    return 0.01;
}

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    return 0.01;
}

-(UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
    return nil;
}

-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    return nil;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}


#pragma mark - 监听textField值改变
- (void)textFieldValueChanged:(UITextField *)textField
{
    [self searchAroundWithKeywords:textField.text];
}

#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [self.view endEditing:YES];
    return YES;
}



@end



版权声明:本文为Alexander_Wei原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。