地图的定位需要使用 BMKLocationService这个类,并遵循BMKLocationServiceDelegate代理
1 基本定位
1.1 声明
@property (nonatomic, strong) BMKLocationService *locService;
1.2 在 viewDidLoad 中初始化
_locService = [[BMKLocationService alloc]init];
1.3 同样设置代理,管理内存
-(void)viewWillAppear:(BOOL)animated
{
[_mapView viewWillAppear];
_mapView.delegate = self; // 此处记得不用的时候需要置nil,否则影响内存的释放
_locService.delegate = self;
}
-(void)viewWillDisappear:(BOOL)animated
{
[_mapView viewWillDisappear];
_mapView.delegate = nil; // 不用时,置nil
_locService.delegate = nil;
}
1.4 在点击方法中,启动定位服务
- (void)position {
//是否显示定位小蓝点,设置为no不显示,可以自定义(这里显示前提要遵循代理方法,不可缺少)
_mapView.showsUserLocation = YES;
//启动LocationService
_mapView.zoomLevel = 14.1; //地图等级,数字越大越清晰
_mapView.userTrackingMode = BMKUserTrackingModeNone;//设定定位模式
[_locService startUserLocationService];
}
1.5 在 BMKLocationService 的代理方法中实现定位
//用户位置更新后,会调用此函数
- (void)didUpdateBMKUserLocation:(BMKUserLocation *)userLocation {
NSLog(@"当前位置%f,%f",userLocation.location.coordinate.latitude,userLocation.location.coordinate.longitude);
// 显示定位点 必须设置地图的中心点,地图才会切换显示到定位位置
_mapView.centerCoordinate = userLocation.location.coordinate;
//设置缩放比例,不设置一次,测试第一次定位时中心总显示在天安门
_mapView.zoomLevel = 14.1;
[_mapView updateLocationData:userLocation];
[_locService stopUserLocationService];
}
此时就可以定位,并显示小蓝点了。
2 问题处理
过程中遇到无法显示定位小蓝点的问题,可能原因:
2.1 info.plist 权限未加
Privacy - Location When In Use Usage Description 允许App在使用时获取GPS的描述
Privacy - Location Always Usage Description 允许永久使用GPS的描述
2.2 若是手动导入的SDK,没有用cocoapods,检查有没有导入mapapi.bundle,这是百度默认的素材包,小蓝点图片在这里面。
以上真机测试就正常了。
2.3 使用模拟器没有定位。
重置模拟器。
若还没有,则可以尝试下面操作,将None改为以下任意一项
2.4 使用模拟器位置不准确,帝都定位到米国,目前没有找到方法,欢迎留言补充。
3 自定义标注-定位图片
一般产品都会要求定位图片使用自己设计的图片,这是就需要用到自定义标注了。
这时应先把系统小蓝点的显示改NO : _mapView.showsUserLocation = NO;
然后来区别2个类:
BMKPointAnnotation:官方解释的是一个点的标注,也就是定位的小蓝点所指代的位置,具有地理的经纬度特性。
BMKAnnotationView:官方解释标注视图,也就是指代那个位置的小蓝点,如果想换图片,则就应该在BMKAnnotationView内部添加image。
3.1 切换小蓝点图片
3.1.1 创建 AnnotionView1 类 继承 BMKAnnotationView,重写 initWithAnnotation 方法,在其中实现自定义UI。
#import <BaiduMapAPI_Map/BMKMapView.h>//只引入所需的单个头文件
@interface AnnotionView1 : BMKAnnotationView
@property (nonatomic, strong) UIImageView *bgImageView;
@end
- (id)initWithAnnotation:(id<BMKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) {
//--------------------------自定义标注视图-------------------------------
self.backgroundColor = [UIColor colorWithWhite:0 alpha:0];
self.centerOffset = CGPointMake(0, 0);
self.frame = CGRectMake(0, 0, 32, 32);
_bgImageView = [[UIImageView alloc]initWithFrame:self.frame];
_bgImageView.image = [UIImage imageNamed:@"cl_cell_selected"];
[self addSubview:_bgImageView];
//--------------------------------------------------------------------
}
return self;
}
3.1.2 声明一个 BMKPointAnnotation变量,并在didUpdateBMKUserLocation 中初始化
@property (nonatomic, strong) BMKPointAnnotation *pointAnnotation;
- (void)didUpdateBMKUserLocation:(BMKUserLocation *)userLocation {
NSLog(@"当前位置%f,%f",userLocation.location.coordinate.latitude,userLocation.location.coordinate.longitude);
// 显示定位点 必须设置地图的中心点,地图才会切换显示到定位位置
_mapView.centerCoordinate = userLocation.location.coordinate;
//设置缩放比例,不设置一次,测试第一次定位时中心总显示在天安门
_mapView.zoomLevel = 14.1;
[_mapView updateLocationData:userLocation];
[_locService stopUserLocationService];
// ------------------自定义标注-------------------------------------
_pointAnnotation = [[BMKPointAnnotation alloc]init];
_pointAnnotation.coordinate = userLocation.location.coordinate;
[_mapView addAnnotation:_pointAnnotation];
[_mapView selectAnnotation:_pointAnnotation animated:YES];
// 设置气泡内容,不设置则不显示气泡
_pointAnnotation.title = @"我在这里";
_pointAnnotation.subtitle = @"公司";
// ----------------------------------------------------------------------
}
3.1.3 实现生成对应标注视图的代理方法 viewForAnnotation
注意:此方法只有在执行了 [_mapView addAnnotation:_pointAnnotation] 后才会调用。
static NSString *myLocationViewID = @"myID";
- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id<BMKAnnotation>)annotation {
AnnotionView1 *newAnnotationView = (AnnotionView1 *)[mapView dequeueReusableAnnotationViewWithIdentifier:myLocationViewID];
if (newAnnotationView == nil) {
newAnnotationView = [[AnnotionView1 alloc] initWithAnnotation:annotation reuseIdentifier:myLocationViewID];
}
return newAnnotationView;
}
3.2 自定义气泡
上图显示的 我在这里.. 就是气泡,点击地图其他地方会消失,点击定位点会出现,这是系统默认的,现在自定义样式。
paopaoView是BMKAnnotationView的一个属性,它就是点击触发的气泡视图。在上述重写BMKAnnotationView的 initWithAnnotation方法中自定义。
- (id)initWithAnnotation:(id<BMKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) {
//--------------------------自定义标注视图-------------------------------
self.backgroundColor = [UIColor colorWithWhite:0 alpha:0];
self.centerOffset = CGPointMake(0, 0);
self.frame = CGRectMake(0, 0, 32, 32);
_bgImageView = [[UIImageView alloc]initWithFrame:self.frame];
_bgImageView.image = [UIImage imageNamed:@"cl_cell_selected"];
[self addSubview:_bgImageView];
//--------------------------------------------------------------------
//--------------------------自定义气泡视图-------------------------------
UIImageView *paoImg = [[UIImageView alloc] initWithFrame:CGRectMake(0, 13, 24, 24)];
paoImg.image =[UIImage imageNamed:@"tabbar_shouye_selected"];
UILabel *paoLbl = [[UILabel alloc]initWithFrame:CGRectMake(30, 0, 70, 50)];
paoLbl.text = @"御书房";
paoLbl.textColor = [UIColor whiteColor];
paoLbl.font = [UIFont systemFontOfSize:15];
UIView *paopao = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 50)];
paopao.backgroundColor = [UIColor colorWithWhite:0 alpha:0.7];
[paopao addSubview:paoImg];
[paopao addSubview:paoLbl];
self.paopaoView = [[BMKActionPaopaoView alloc]initWithCustomView:paopao];
//--------------------------------------------------------------------
}
return self;
}
我们什么时候重写BMKPointAnnotation呢,一般来说他只是传个地理位置信息,当我们在地图上想要显示多个地理位置信息的时候,比如后台返回来一个数组,里面每个元素都是一个字典,每个字典代表一个单位,除了地理位置信息,还有其他信息,比如名字,图片等,对应的是每个地理位置,这时候重写BMKPointAnnotation,并在其中定义一个model属性,用来接收后台返回来的model信息串。然后声明这个pointAnnotation类的对象,并给他赋值后台返回来的model信息串中的位置信息,并将整个model传给他,后面的操作和上面的步骤一样。