项目截图
项目需求
1.公司要求模仿微信/QQ的定位选址效果
2.根据关键字进行定位选址
本项目中用到了高德地图的POI周边搜索功能、单次定位功能、关键字搜索
本人对高德的API进行了一个简单的封装,
SLocationManager
定位管理者,可以进行单次搜索,持续搜索,关键字搜索,获取当前的经纬度...如果有什么不明白的地方直接看官方文档,文档真的很详细,注释什么的很详细,这个工具类是直接从项目中拷贝过来的,由于工作时间紧张,所以没有demo,😂,小伙伴们不要问demo了,哈哈.👇的快速通道可以帮助小伙伴们快速熟悉高德API,如果有什么疑问,欢迎提问
快速通道
1.根据关键字检索POI(Point of Interest,兴趣点)
关键字检索介绍
根据关键字检索适用于在某个城市搜索某个名称相关的POI,例如:查找北京市的“肯德基”。
注意:关键字未设置城市信息(默认为全国搜索)时,如果涉及多个城市数据返回,仅会返回建议城市,请根据APP需求,选取城市进行搜索。
进入通道➡️
2.检索周边POI
周边检索介绍
适用于搜索某个位置附近的POI,可设置POI的类别,具体查询所在位置的餐饮类、住宅类POI,例如:查找天安门附近的厕所等等场景。
****说明****:
- 1、支持指定查询POI的类别。高德地图的POI类别共20个大类,分别为:汽车服务、汽车销售、汽车维修、摩托车服务、餐饮服务、购物服务、生活服务、体育休闲服务、医疗保健服务、住宿服务、风景名胜、商务住宅、政府机构及社会团体、科教文化服务、交通设施服务、金融保险服务、公司企业、道路附属设施、地名地址信息、公共设施,同时,每个大类别都还有二级以及三级的细小划分,具体的POI类别请参考:POI分类编码表。
- 2、不设置POI的类别,默认返回“餐饮服务”、“商务住宅”、“生活服务”这三种类别的POI。
进入通道➡️
SLocationManager.h
#import <Foundation/Foundation.h>
#import <AMapLocationKit/AMapLocationKit.h>
#import <AMapSearchKit/AMapSearchKit.h>
typedef void(^SLocationManagerDidUpdateLocationHandle)(CLLocation *newLocation, NSString *newLatitude, NSString *newLongitude);
typedef void (^SLocationManagerDidGetPOISearchResponse)(AMapPOISearchResponse *response);
typedef void (^SLocationManagerDidGetTipsResponse)(AMapInputTipsSearchResponse *response);
typedef void (^SLocationManagerErrorResponse)(NSString *response);
@interface SLocationManager : NSObject
/** 开始定位*/
- (void)startSerialLocation;
/**开始单次定位*/
- (void)startSingleLocation;
// 快速创建一个locationManager
+ (instancetype)sharedManager;
/** 开始周边搜索🔍 */
- (void)beginAroundSearch;
/**
搜索更多周边信息
@param page 搜索的页数
*/
- (void)aroundSearchMore:(NSInteger)page;
/** 更新定位回调*/
- (void)setUpLocationManagerUpdateLocationHandle:(SLocationManagerDidUpdateLocationHandle)updateLocationHandle;
/** 定位到兴趣点 */
- (void)locationManagerDidGetPOISearchResponse:(SLocationManagerDidGetPOISearchResponse)POISearchResponse;
/** 获取到提示搜索词 */
- (void)locationManagerDidGetTipsResponse:(SLocationManagerDidGetTipsResponse)tipsResponse;
/**
关键字搜索
@param keywords 搜索关键字 必传参数
@param city 搜索城市
@param page 搜索页数
*/
- (void)keywordsSearchWithKeywords:(NSString *)keywords city:(NSString *)city page:(NSInteger)page;
/** 提示搜索 */
- (void)tipsSearchWithKeywords:(NSString *)key city:(NSString *)city ;
/** 是否可以定位*/
@property (nonatomic, assign) BOOL canLocationFlag;
/** 是否有经纬度*/
@property (nonatomic, assign) BOOL hasLocation;
/** 经纬度 */
- (NSString *)curLatitudeAndLongitude;
@end
SLocationManager.m
#import "SLocationManager.h"
@interface SLocationManager ()<AMapSearchDelegate,AMapLocationManagerDelegate>
@property (nonatomic, strong) AMapLocationManager *locationManager;
@property (strong, nonatomic) AMapSearchAPI *search;
@end
static SLocationManager *_singleton = nil;
@implementation SLocationManager
{
SLocationManagerDidUpdateLocationHandle _updateLocationHandle;
SLocationManagerDidGetPOISearchResponse _POISearchResponse;
SLocationManagerDidGetTipsResponse _tipsResponse;
BOOL isSearch;
}
- (AMapLocationManager *)locationManager {
if (!_locationManager) {
AMapLocationManager *locationManager = [[AMapLocationManager alloc] init];
_locationManager = locationManager;
locationManager.delegate = self;
//iOS 9(不包含iOS 9) 之前设置允许后台定位参数,保持不会被系统挂起
locationManager.pausesLocationUpdatesAutomatically = NO;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.allowsBackgroundLocationUpdates = NO;
}
return _locationManager;
}
- (AMapSearchAPI *)search
{
if (_search == nil) {
_search = [[AMapSearchAPI alloc] init];
_search.delegate = self;
}
return _search;
}
+ (instancetype)sharedManager {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_singleton = [[SLocationManager alloc] init];
});
return _singleton;
}
- (void)setUpLocationManagerUpdateLocationHandle:(SLocationManagerDidUpdateLocationHandle)updateLocationHandle {
_updateLocationHandle = updateLocationHandle;
}
- (void)locationManagerDidGetPOISearchResponse:(SLocationManagerDidGetPOISearchResponse)POISearchResponse {
_POISearchResponse = POISearchResponse;
}
// 开始定位
- (void)startSerialLocation {
if (self.canLocationFlag == NO) {
return ;
}
//iOS 9(包含iOS 9)之后新特性:将允许出现这种场景,同一app中多个locationmanager:一些只能在前台定位,另一些可在后台定位,并可随时禁止其后台定位。
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
self.locationManager.allowsBackgroundLocationUpdates = YES;
}
//开始持续定位
[self.locationManager startUpdatingLocation];
}
// 停止定位
- (void)stopSerialLocation {
[self.locationManager stopUpdatingLocation];
}
// 开始单次定位
- (void)startSingleLocation {
if (self.canLocationFlag == NO) {
return ;
}
// 带逆地理(返回坐标和地址信息)。将下面代码中的 YES 改成 NO ,则不会返回地址信息。
[self.locationManager requestLocationWithReGeocode:YES completionBlock:^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error) {
if (error)
{
NSLog(@"locError:{%ld - %@};", (long)error.code, error.localizedDescription);
if (error.code == AMapLocationErrorLocateFailed)
{
return;
}
}
[self saveLocation:location];
if (regeocode)
{
NSLog(@"reGeocode:%@", regeocode);
}
}];
}
#pragma mark - AMapLocationManager
// 定位错误
- (void)amapLocationManager:(AMapLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(@"error = %@", error);
}
// 定位结果
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateLocation:(CLLocation *)newLocation reGeocode:(AMapLocationReGeocode *)reGeocode{
[self saveLocation:newLocation];
[self stopSerialLocation];
}
- (void)saveLocation:(CLLocation *)newLocation {
// 纬度
NSString *currentLatitude = [[NSString alloc]
initWithFormat:@"%f",
newLocation.coordinate.latitude];
// 经度
NSString *currentLongitude = [[NSString alloc]
initWithFormat:@"%f",
newLocation.coordinate.longitude];
[[NSUserDefaults standardUserDefaults] setObject:currentLatitude forKey:kSUserCurrentLatitude];
[[NSUserDefaults standardUserDefaults] setObject:currentLongitude forKey:kSUserCurrentLongitude];
[[NSUserDefaults standardUserDefaults] synchronize];
if (_updateLocationHandle) {
_updateLocationHandle(newLocation, currentLatitude, currentLongitude);
}
if (isSearch) {
[self beginAroundSearch];
}
}
/** 经纬度 */
- (NSString *)curLatitudeAndLongitude {
NSString *latitude = [[NSUserDefaults standardUserDefaults] valueForKey:kSUserCurrentLatitude];
NSString *longitude = [[NSUserDefaults standardUserDefaults] valueForKey:kSUserCurrentLongitude];
return [NSString stringWithFormat:@"%@,%@",latitude,longitude];
}
- (BOOL)isCanLocationFlag {
if ([CLLocationManager locationServicesEnabled] && ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse)) {
return YES;
} else {
return NO;
}
}
- (BOOL)hasLocation {
return [[[NSUserDefaults standardUserDefaults] objectForKey:kSUserCurrentLongitude] length] && [[[NSUserDefaults standardUserDefaults] objectForKey:kSUserCurrentLatitude] length];
}
#pragma mark - 周边搜索
- (void)beginAroundSearch {
if (![self hasLocation]) {
isSearch = YES;
[self startSingleLocation];
return;
}
NSString *currentLatitude = [[NSUserDefaults standardUserDefaults] objectForKey:kSUserCurrentLatitude];
NSString *currentLongitude = [[NSUserDefaults standardUserDefaults] objectForKey:kSUserCurrentLongitude];
AMapPOIAroundSearchRequest *request = [[AMapPOIAroundSearchRequest alloc] init];
request.location = [AMapGeoPoint locationWithLatitude:[currentLatitude floatValue] longitude:[currentLongitude floatValue]];
request.keywords = @"";
/* 按照距离排序. */
request.sortrule = 0;
request.requireExtension = YES;
[self.search AMapPOIAroundSearch:request];
}
#pragma mark - AMapSearchDelegate
- (void)onPOISearchDone:(AMapPOISearchBaseRequest *)request response:(AMapPOISearchResponse *)response{
// if (response.pois.count == 0){
//
// return;
// }
for(AMapPOI *poi in response.pois){
NSLog(@"%@.%@-%@-%@",poi.name,poi.district,poi.businessArea,poi.address);
}
if (_POISearchResponse) {
_POISearchResponse(response);
}
}
- (void)aroundSearchMore:(NSInteger)page {
NSString *currentLatitude = [[NSUserDefaults standardUserDefaults] objectForKey:kSUserCurrentLatitude];
NSString *currentLongitude = [[NSUserDefaults standardUserDefaults] objectForKey:kSUserCurrentLongitude];
AMapPOIAroundSearchRequest *request = [[AMapPOIAroundSearchRequest alloc] init];
request.location = [AMapGeoPoint locationWithLatitude:[currentLatitude floatValue] longitude:[currentLongitude floatValue]];
request.keywords = @"";
/* 按照距离排序. */
request.sortrule = 0;
request.requireExtension = YES;
request.page = page;
[self.search AMapPOIAroundSearch:request];
}
#pragma mark - 关键字搜索
- (void)keywordsSearchWithKeywords:(NSString *)keywords city:(NSString *)city page:(NSInteger)page{
AMapPOIKeywordsSearchRequest *request = [[AMapPOIKeywordsSearchRequest alloc] init];
request.keywords = keywords;
request.city = city;
// request.types = @"高等院校";
request.requireExtension = YES;
/* 搜索SDK 3.2.0 中新增加的功能,只搜索本城市的POI。*/
// request.cityLimit = YES;
// request.requireSubPOIs = YES;
request.page = page;
[self.search AMapPOIKeywordsSearch:request];
}
#pragma mark - 提示搜索
- (void)tipsSearchWithKeywords:(NSString *)key city:(NSString *)city {
AMapInputTipsSearchRequest *tips = [[AMapInputTipsSearchRequest alloc] init];
tips.keywords = key;
tips.city = city;
[self.search AMapInputTipsSearch:tips];
}
/* 输入提示回调. */
- (void)onInputTipsSearchDone:(AMapInputTipsSearchRequest *)request response:(AMapInputTipsSearchResponse *)response
{
// if (response.tips.count == 0) {
// return;
// }
if (_tipsResponse) {
_tipsResponse(response);
}
}
- (void)locationManagerDidGetTipsResponse:(SLocationManagerDidGetTipsResponse)tipsResponse {
_tipsResponse = tipsResponse;
}
@end