其实今年我也是才进入到工作岗位不久,因为瘟疫来袭,我所在的城市又被称为“瘟疫之源”,一路之下,我竟然好几个月没了,工作,我们是被戏称“49年9月30号入KuoMinTang”的人,但是为了生存,有些事情,无可奈何
总之进入正题
查看平面图详情的功能
有一个需求是要查看一个楼层平面图的功能,就是点击图片,展示的是一个比较大的图,但是我实际上显示的是比较小(虽然后端用Html语言,传入的图片比较大,可能是apple在对webView上进行了适配)虽然可以伸缩,但是网页也不方便给别人看,特别是年纪稍微大点的老人,我到后来请教到的办法就是,用scrollView + UIImageView这个体系,UIImageView用sd_webimage加载图,来实现这个功能
NSString *urlStr = [NSString stringWithFormat:@"http://192.168.0.25:8091%@",self.inHospital.Image_url];
UIScrollView *scrollView = [[UIScrollView alloc]init];
scrollView.frame = CGRectMake(0, NAVH + STATUSH + 60, Screen_Width, Screen_Height - NAVH - STATUSH - 60);
[self.view addSubview:scrollView];
self.scrollView = scrollView;
// 设置最大伸缩比例
self.scrollView.maximumZoomScale = 2.0;
// 设置最小伸缩比例
self.scrollView.minimumZoomScale = 0.5;
self.scrollView.delegate = self;
UIImageView *imageView = [[UIImageView alloc]init];
[self.scrollView addSubview:imageView];
self.urlImageV = imageView;
[[SDWebImageManager sharedManager]loadImageWithURL:[NSURL URLWithString:urlStr] options:0 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
self.urlImageV.image = image;
CGFloat imageWidth = image.size.width * 0.3;
CGFloat imageHeight = image.size.height * 0.3;
CGFloat screenW = self.scrollView.bounds.size.width;
CGFloat screenH = self.scrollView.bounds.size.height;
self.urlImageV.frame = CGRectMake(0, 0, imageWidth, imageHeight);
self.scrollView.contentSize = self.urlImageV.bounds.size;
CGFloat offsetX = self.scrollView.contentSize.width * 0.5 - screenW * 0.5;
[self.scrollView scrollRectToVisible:CGRectMake(offsetX, 0, screenW, screenH) animated:YES];
}];
然后调用代理方法(注意:上面的urlStr是模型数据,对应调用即可)
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return self.urlImageV;
}
在一个需要webView的底部添加一个原生控件的情况
当时需要一个用户在webView里需要填表,webView的高度要获取之后,我才能在后续添加一个原生控件,所以我得知道如何获取高度,之前有看到在- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation这个代理方法获取,但是我似乎没能及时获取到,所以采取的第二个方法,就是KVO
-(void)setupKVO{
// 添加kvo监听webview的scrollView.contentSize变化
[self.webView addObserver:self forKeyPath:@"scrollView.contentSize" options:NSKeyValueObservingOptionNew context:nil];
}
// 使用kvo监听到的contensize变化,之所以在这里设置,因为webview加载的内容多的时候 是一段一段加载初开的,所以webview的contensize是实时变化的,所以在这里监听到可以以达到实时改变,不至于页面卡顿
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if (object == self.webView && [keyPath isEqual:@"scrollView.contentSize"]) {
self.wbContentHeight = self.webView.scrollView.contentSize.height;
[self.webView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(self.wbContentHeight);
}];
}
}
- (void)dealloc{
if (self.information) {
[self.webView removeObserver:self forKeyPath:@"scrollView.contentSize" context:nil];
}
}
iOS14UIPageControl的问题
这个是有个网友给我留言我突然想起来了这个也是个问题,因为之前想采纳他的建议去设置,但是发现我似乎又看到了原生的点,又有自己设置的线,所以我后续用了另外一个网友的内容,所以在此复制过来了,先感谢他(先创建一个分类)
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/**
结合runtime 自定义UIPageControl
*/
@interface UIPageControl (Fix4iOS14)
/** 设置page control图片 */
- (void)kn_SetCurrentImage:(UIImage *)currentImage pageImage:(UIImage *)pageImage;
@end
NS_ASSUME_NONNULL_END
#import "UIPageControl+Fix4iOS14.h"
#import <objc/runtime.h>
@interface UIPageControl ()
@property (nonatomic, strong) UIImage *KN_currentImage;
@property (nonatomic, strong, readonly) NSMutableDictionary<NSString *, UIImageView *> *KN_indicatorImages;
@end
@implementation UIPageControl (Fix4iOS14)
static BOOL KN_shouldTreatImageAsTemplate(UIImageView *obj, SEL sel, id arg1) {
UIPageControl *pageControl = (id)obj;
while ((pageControl = (id)pageControl.superview)) {
if ([pageControl isKindOfClass:[UIPageControl class]]) {
if (pageControl.KN_currentImage) {
[pageControl.KN_indicatorImages setValue:obj forKeyPath:[[obj valueForKeyPath:@"_page"] description]];
return NO;
} else {
break;
}
}
}
// 默认走系统的实现
return ((BOOL (*)(UIView *, SEL, id))class_getMethodImplementation(obj.superclass, sel))(obj, sel, arg1);
}
+ (void)load {
if (@available(iOS 14, *)) {
Class clazz = NSClassFromString(@"_UIPageIndicatorView");
SEL sel = NSSelectorFromString(@"_shouldTreatImageAsTemplate:");
class_addMethod(clazz, sel, (IMP)KN_shouldTreatImageAsTemplate, method_getTypeEncoding(class_getInstanceMethod(clazz, sel)));
method_exchangeImplementations(class_getInstanceMethod(self, @selector(setCurrentPage:)),
class_getInstanceMethod(self, @selector(KN_setCurrentPage:)));
method_exchangeImplementations(class_getInstanceMethod(self, @selector(setNumberOfPages:)),
class_getInstanceMethod(self, @selector(KN_setNumberOfPages:)));
}
}
- (void)KN_setCurrentPage:(NSInteger)currentPage {
[self KN_setCurrentPage:currentPage];
[self KN_pageControlValueChange];
}
- (void)KN_setNumberOfPages:(NSInteger)numberOfPages {
NSInteger currentPage = self.currentPage;
[self KN_setNumberOfPages:numberOfPages];
if (numberOfPages <= currentPage) {
[self setIndicatorImage:self.KN_currentImage forPage:self.currentPage];
}
[self KN_refreshIndicatorTintColor];
}
- (void)setKN_currentImage:(UIImage *)KN_currentImage {
objc_setAssociatedObject(self, @selector(KN_currentImage), KN_currentImage, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIImage *)KN_currentImage {
return objc_getAssociatedObject(self, _cmd);
}
- (NSMutableDictionary<NSString *, UIImageView *> *)KN_indicatorImages {
if (!objc_getAssociatedObject(self, _cmd)) {
objc_setAssociatedObject(self, _cmd, [NSMutableDictionary dictionary], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return objc_getAssociatedObject(self, _cmd);
}
/** 设置page control图片 */
- (void)kn_SetCurrentImage:(UIImage *)currentImage pageImage:(UIImage *)pageImage {
if (@available(iOS 14, *)) {
self.KN_currentImage = currentImage;
self.preferredIndicatorImage = pageImage;
[self removeTarget:self
action:@selector(KN_pageControlValueChange)
forControlEvents:UIControlEventValueChanged];
[self addTarget:self
action:@selector(KN_pageControlValueChange)
forControlEvents:UIControlEventValueChanged];
dispatch_async(dispatch_get_main_queue(), ^{
[self KN_refreshIndicatorTintColor];
});
} else {
[self setValue:currentImage forKeyPath:@"_currentPageImage"];
[self setValue:pageImage forKeyPath:@"_pageImage"];
}
}
- (void)KN_pageControlValueChange {
for (NSInteger i = 0; i < self.numberOfPages; i++) {
if (i == self.currentPage) {
if (@available(iOS 14.0, *)) {
[self setIndicatorImage:self.KN_currentImage forPage:self.currentPage];
} else {
// Fallback on earlier versions
}
} else {
if (@available(iOS 14.0, *)) {
[self setIndicatorImage:self.preferredIndicatorImage forPage:i];
} else {
// Fallback on earlier versions
}
}
}
}
- (void)KN_refreshIndicatorTintColor {
for (NSInteger i = 0; i < self.numberOfPages; i++) {
[self.KN_indicatorImages[@(i).description] tintColorDidChange];
}
}
@end
使用:
UIPageControl *pageControl = [[UIPageControl alloc] init];
pageControl.hidesForSinglePage = YES;
if (@available(iOS 13.0, *)) {
[pageControl kn_SetCurrentImage:[UIImage imageNamed:@"compose_keyboard_dot_selected"] pageImage:[UIImage imageNamed:@"compose_keyboard_dot_normal"]];
} else {
// Fallback on earlier versions
[pageControl setValue:[UIImage imageWithName:@"compose_keyboard_dot_selected"] forKeyPath:@"_currentPageImage"];
[pageControl setValue:[UIImage imageWithName:@"compose_keyboard_dot_normal"] forKeyPath:@"_pageImage"];
}
[self addSubview:pageControl];
self.pageControl = pageControl;
注意:如果count为空的时候,会闪退,所以在设置模型的时候会再做判断
- (void)setEmotions:(NSArray *)emotions
{
_emotions = emotions;
// 设置总页数
NSInteger totalPages = (emotions.count + TFEmotionMaxCountPerPage - 1) / TFEmotionMaxCountPerPage;
NSInteger currentGridViewCount = self.scrollView.subviews.count;
if (totalPages <= 0) {
self.pageControl.hidden = YES;
// self.pageControl.numberOfPages = totalPages;
}else if (totalPages == 1){
self.pageControl.hidesForSinglePage = YES;
self.pageControl.numberOfPages = totalPages;
}else{
self.pageControl.hidden = NO;
self.pageControl.numberOfPages = totalPages;
}
self.pageControl.currentPage = 0;
[self setNeedsLayout];
self.scrollView.contentOffset = CGPointZero;
}
跳转问题了
这个应该是我的低级失误了,这个其实是给我自己提醒的,其实配置一直是没错
[[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"baidumap://"]]
但是我手机没装百度地图,数组还是添加了。。。
[self.mapArray addObject:@"百度地图"];
到后来才发现是这里要这么添加,因为之前没有://
image.png
关于appdelegate里的window问题
其实很多代码里写的还是
UIApplication.sharedApplication.delegate.keyWindow
事实上xcode的appdelegate只有window了,所以在有的第三方用起来的时候可能会闪退,所以解决要么是更新第三方,要么就只能用到闪退的位置的时候,全局断点来调试了
使用百度地图的一点体会(地图定位,地图选点,选点的范围内的建筑名称,通过关键字搜索)算是给自己看的吧
#import "MapAddressSelectViewController.h"
#import <BaiduMapAPI_Base/BMKBaseComponent.h>//引入base相关所有的头文件
#import <BaiduMapAPI_Map/BMKMapComponent.h>//引入地图功能所有的头文件
#import <BMKLocationKit/BMKLocationManager.h>
#import <BaiduMapAPI_Search/BMKSearchComponent.h>
#import <BaiduMapAPI_Utils/BMKUtilsComponent.h>
#import "MapListViewCell.h"
#import <CoreLocation/CoreLocation.h>
@interface MapAddressSelectViewController ()<BMKMapViewDelegate,BMKLocationManagerDelegate,BMKGeoCodeSearchDelegate,BMKPoiSearchDelegate,UITextFieldDelegate,UITableViewDataSource,UITableViewDelegate>
@property (nonatomic, strong) BMKMapView *mapView;
@property (nonatomic, strong) BMKLocationManager *locationManager; //定位对象
@property (nonatomic, strong) BMKUserLocation *userLocation; //当前位置对象
@property (nonatomic, strong) BMKGeoCodeSearch *search; //反地理编码搜索
/** 获取方圆的地址数据的搜索 */
@property (strong,nonatomic) BMKPoiSearch *poiSearch;
/** 邮编 */
@property (copy,nonatomic) NSString *areaCode;
/** 获取区域名字 */
@property (copy,nonatomic) NSString *cityName;
/** 地址view */
@property (weak,nonatomic) UIView *addressView;
/** 地址搜索框 */
@property (strong,nonatomic) UIButton *addrBtn;
/** 表格 */
@property (weak,nonatomic) UITableView *tableView;
/// POI列表,成员是BMKPoiInfo
@property (nonatomic, strong) NSMutableArray<BMKPoiInfo *> *poiInfos;
/** 选中的poiInfo */
@property (strong,nonatomic) BMKPoiInfo *selectedPoiInfo;
/// 选中的地址数组
@property (nonatomic, strong) NSMutableArray *selectArr;
@end
@implementation MapAddressSelectViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"选择地址";
self.view.backgroundColor = [UIColor whiteColor];
[self mapSetting];
[self setupNav];
// //不显示定位图层
// _mapView.showsUserLocation = NO;
UIView *addressView = [[UIView alloc]init];
addressView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:addressView];
[addressView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(0);
make.bottom.mas_equalTo(0);
make.height.mas_equalTo(300);
}];
self.addressView = addressView;
UITextField *addrTextF = [[UITextField alloc]init];
addrTextF.textColor = [UIColor colorWithHexString:@"333333"];
addrTextF.font = [UIFont hx_pingFangFontOfSize:14.0];
addrTextF.layer.cornerRadius = 5;
addrTextF.layer.masksToBounds = YES;
addrTextF.backgroundColor = [UIColor colorWithHexString:@"f4f4f4"];
addrTextF.leftView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 6, 0)];
addrTextF.leftViewMode = UITextFieldViewModeAlways;
[addrTextF addTarget:self action:@selector(textChanged:) forControlEvents:UIControlEventEditingChanged];
addrTextF.returnKeyType = UIReturnKeySearch;
addrTextF.delegate = self;
[addressView addSubview:addrTextF];
[addrTextF mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.mas_equalTo(15);
make.right.mas_equalTo(-15);
make.height.mas_equalTo(34);
}];
UIButton *addrBtn = [UIButton buttonWithType:UIButtonTypeCustom];
addrBtn.userInteractionEnabled = NO;
[addrBtn setTitle:@"搜索地点" forState:UIControlStateNormal];
addrBtn.titleLabel.font = [UIFont hx_pingFangFontOfSize:14.0];
[addrBtn setTitleColor:[UIColor colorWithHexString:@"989898"] forState:UIControlStateNormal];
[addrBtn setImage:[[UIImage imageNamed:@"addrSachi"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forState:UIControlStateNormal];
addrBtn.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
[addrTextF addSubview:addrBtn];
self.addrBtn = addrBtn;
[addrBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(addrTextF);
}];
UITableView *tableView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStylePlain];
tableView.backgroundColor = [UIColor whiteColor];
tableView.dataSource = self;
tableView.delegate = self;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[addressView addSubview:tableView];
[tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(0);
make.top.mas_equalTo(addrTextF.mas_bottom).offset(15);
make.bottom.mas_equalTo(0);
}];
[tableView registerNib:[UINib nibWithNibName:@"MapListViewCell" bundle:nil] forCellReuseIdentifier:@"MapListViewCell"];
self.tableView = tableView;
UIView *locaView = [[UIView alloc]init];
locaView.backgroundColor = [UIColor clearColor];
locaView.userInteractionEnabled = YES;
[self.view addSubview:locaView];
[locaView mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.mas_equalTo(-10);
make.bottom.mas_equalTo(addressView.mas_top).offset(10);
make.width.height.mas_equalTo(60);
}];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(locationTap)];
[locaView addGestureRecognizer:tap];
UIImageView *locaV = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"addLoca"]];
[locaView addSubview:locaV];
[locaV mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.right.mas_equalTo(0);
make.width.height.mas_equalTo(40);
}];
}
-(void)mapSetting{
self.mapView = [[BMKMapView alloc]initWithFrame:self.view.bounds];
self.mapView.delegate = self;
// 将当前地图显示缩放等级设置为21级
[_mapView setZoomLevel:21];
//开启定位服务
[self.locationManager startUpdatingLocation];
[self.locationManager startUpdatingHeading];
//显示定位图层
_mapView.showsUserLocation = YES;
//设置定位模式为定位跟随模式
// _mapView.userTrackingMode = BMKUserTrackingModeFollow;
[self.view addSubview:self.mapView];
self.search = [[BMKGeoCodeSearch alloc]init];
self.search.delegate = self;
self.poiSearch = [[BMKPoiSearch alloc]init];
self.poiSearch.delegate = self;
}
-(void)setupNav{
UIView *nav = [[UIView alloc]init];
nav.backgroundColor = [UIColor clearColor];
[self.view addSubview:nav];
[nav mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(XYStatusBarH);
make.left.right.mas_equalTo(0);
make.height.mas_equalTo(XYNavBarH);
}];
UIView *leftV = [[UIView alloc]init];
leftV.backgroundColor = [UIColor clearColor];
[nav addSubview:leftV];
[leftV mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(15);
make.top.bottom.mas_equalTo(0);
make.width.mas_equalTo(45);
}];
UITapGestureRecognizer *cancelTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(cancelClick)];
[leftV addGestureRecognizer:cancelTap];
UILabel *cancelLb = [[UILabel alloc]init];
cancelLb.text = @"取消";
cancelLb.textColor = [UIColor colorWithHexString:@"333333"];
cancelLb.font = [UIFont hx_pingFangFontOfSize:14.0];
[leftV addSubview:cancelLb];
[cancelLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0);
make.centerY.mas_equalTo(leftV.mas_centerY);
}];
UIButton *saveBtn = [UIButton buttonWithType:(UIButtonTypeCustom)];
[saveBtn setTitle:@"确定" forState:(UIControlStateNormal)];
saveBtn.titleLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:14.0];
[saveBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
saveBtn.backgroundColor = [UIColor colorWithHexString:@"07c05f"];
saveBtn.layer.cornerRadius = 3;
saveBtn.layer.masksToBounds = YES;
[nav addSubview:saveBtn];
[saveBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.mas_equalTo(-15);
make.width.mas_equalTo(50);
make.height.mas_equalTo(25);
make.centerY.mas_equalTo(leftV.mas_centerY);
}];
xy_weakify(self);
[saveBtn bk_addEventHandler:^(id _Nonnull sender) {
ZRLog(@"经纬度%f %f",weakself.selectedPoiInfo.pt.latitude,weakself.selectedPoiInfo.pt.longitude);
ZRLog(@"地址%@ %@",weakself.selectedPoiInfo.name,weakself.selectedPoiInfo.address);
ZRLog(@"%@",weakself.areaCode);
if (weakself.addressSelectBlock) {
weakself.addressSelectBlock(weakself.selectedPoiInfo.pt, weakself.selectedPoiInfo.address, weakself.selectedPoiInfo.name);
}
if (weakself.ruleAddressSelectBlock) {
weakself.ruleAddressSelectBlock(weakself.selectedPoiInfo.pt, weakself.selectedPoiInfo.address, weakself.areaCode,weakself.selectedPoiInfo.name);
}
[weakself.navigationController popViewControllerAnimated:YES];
} forControlEvents:UIControlEventTouchUpInside];
}
-(void)cancelClick{
[self.navigationController popViewControllerAnimated:YES];
}
-(void)textChanged:(UITextField *)textField{
if (textField.text.length > 0) {
self.addrBtn.hidden = YES;
}else{
self.addrBtn.hidden = NO;
}
//初始化请求参数类BMKCitySearchOption的实例
BMKPOICitySearchOption *cityOption = [[BMKPOICitySearchOption alloc] init];
//检索关键字,必选。举例:小吃
cityOption.keyword = textField.text;
//区域名称(市或区的名字,如北京市,海淀区),最长不超过25个字符,必选
cityOption.city = self.cityName;
//检索分类,可选,与keyword字段组合进行检索,多个分类以","分隔。举例:美食,烧烤,酒店
// cityOption.tags = @[@"美食",@"烧烤"];
//区域数据返回限制,可选,为YES时,仅返回city对应区域内数据
cityOption.isCityLimit = YES;
//POI检索结果详细程度
//cityOption.scope = BMK_POI_SCOPE_BASIC_INFORMATION;
//检索过滤条件,scope字段为BMK_POI_SCOPE_DETAIL_INFORMATION时,filter字段才有效
//cityOption.filter = filter;
//分页页码,默认为0,0代表第一页,1代表第二页,以此类推
cityOption.pageIndex = 0;
//单次召回POI数量,默认为10条记录,最大返回20条
cityOption.pageSize = 10;
BOOL flag = [self.poiSearch poiSearchInCity:cityOption];
if (flag) {
ZRLog(@"POI周边检索成功");
}else{
ZRLog(@"POI周边检索失败");
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.navigationBar.hidden = YES;
[_mapView viewWillAppear];
}
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
self.navigationController.navigationBar.hidden = NO;
[_mapView viewWillDisappear];
}
-(void)locationTap{
[self.mapView removeAnnotations:self.mapView.annotations];
//开启定位服务
[self.locationManager startUpdatingLocation];
[self.locationManager startUpdatingHeading];
//设置定位模式为定位跟随模式
// self.mapView.userTrackingMode = BMKUserTrackingModeFollow;
}
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[self.view endEditing:YES];
[self textChanged:textField];
return YES;
}
#pragma mark - BMKLocationManagerDelegate
/**
@brief 当定位发生错误时,会调用代理的此方法
@param manager 定位 BMKLocationManager 类
@param error 返回的错误,参考 CLError
*/
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didFailWithError:(NSError * _Nullable)error {
NSLog(@"定位失败");
}
/**
@brief 该方法为BMKLocationManager提供设备朝向的回调方法
@param manager 提供该定位结果的BMKLocationManager类的实例
@param heading 设备的朝向结果
*/
- (void)BMKLocationManager:(BMKLocationManager *)manager didUpdateHeading:(CLHeading *)heading {
if (!heading) {
return;
}
ZRLog(@"用户方向更新:%f",self.userLocation.location.coordinate.latitude);
self.userLocation.heading = heading;
[_mapView updateLocationData:self.userLocation];
}
/**
@brief 连续定位回调函数
@param manager 定位 BMKLocationManager 类
@param location 定位结果,参考BMKLocation
@param error 错误信息。
*/
- (void)BMKLocationManager:(BMKLocationManager *)manager didUpdateLocation:(BMKLocation *)location orError:(NSError *)error {
if (error) {
NSLog(@"locError:{%ld - %@};", (long)error.code, error.localizedDescription);
}
if (!location) {
return;
}
self.userLocation.location = location.location;
//实现该方法,否则定位图标不出现
[_mapView updateLocationData:self.userLocation];
//设置当前地图的中心点
self.mapView.centerCoordinate = self.userLocation.location.coordinate;
// 这里可以获取地理位置的经纬度
BMKReverseGeoCodeSearchOption *reverseGeoCodeOption = [[BMKReverseGeoCodeSearchOption alloc]init];
reverseGeoCodeOption.location = CLLocationCoordinate2DMake(self.userLocation.location.coordinate.latitude, self.userLocation.location.coordinate.longitude);
// 是否访问最新版行政区划数据(仅对中国数据生效)
reverseGeoCodeOption.isLatestAdmin = YES;
BOOL flag = [self.search reverseGeoCode: reverseGeoCodeOption];
if (flag) {
NSLog(@"逆geo检索发送成功");
} else {
NSLog(@"逆geo检索发送失败");
}
//定位之后马上关闭定位服务
[self.locationManager stopUpdatingLocation];
[self.locationManager stopUpdatingHeading];
}
#pragma mark - BMKGeoCodeSearchDelegate
/**
反向地理编码检索结果回调
@param searcher 检索对象
@param result 反向地理编码检索结果
@param error 错误码,@see BMKCloudErrorCode
*/
- (void)onGetReverseGeoCodeResult:(BMKGeoCodeSearch *)searcher result:(BMKReverseGeoCodeSearchResult *)result errorCode:(BMKSearchErrorCode)error {
if (error == BMK_SEARCH_NO_ERROR) {
//在此处理正常结果
ZRLog(@"%f",result.location.latitude);
self.areaCode = result.addressDetail.adCode;
// 这个是定位之后获取的一个地址名字,方便搜索的时候用的
self.cityName = result.addressDetail.streetName;
[self.poiInfos removeAllObjects];
[self.poiInfos addObjectsFromArray:result.poiList];
[self.selectArr removeAllObjects];
for (int i = 0;i < self.poiInfos.count;i ++) {
BMKPoiInfo *point = self.poiInfos[i];
// 由于不能存逻辑值,而且不能用百度的模型,那么存字符串了
NSString *select = @"未选中";
if (i == 0) { // 默认第一个选中
self.selectedPoiInfo = point;
select = @"选中";
}
[self.selectArr addObject:select];
}
[self.tableView reloadData];
} else {
NSLog(@"检索失败");
}
}
#pragma mark - BMKMapViewDelegate
/**
根据anntation生成对应的annotationView
@param mapView 地图View
@param annotation 指定的标注
@return 生成的标注View
*/
- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id<BMKAnnotation>)annotation {
/**
根据指定标识查找一个可被复用的标注,用此方法来代替新创建一个标注,返回可被复用的标注
*/
BMKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"annotationViewIdentifier"];
if (!annotationView) {
/**
初始化并返回一个annotationView
@param annotation 关联的annotation对象
@param reuseIdentifier 如果要重用view,传入一个字符串,否则设为nil,建议重用view
@return 初始化成功则返回annotationView,否则返回nil
*/
annotationView = [[BMKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"annotationViewIdentifier"];
}
//annotationView关联的annotation
annotationView.annotation = annotation;
return annotationView;
}
/**
*点中地图空白处会回调此接口(这里可以用作添加大头针)
*@param mapView 地图View
*@param coordinate 空白处坐标点的经纬度
*/
- (void)mapView:(BMKMapView *)mapView onClickedMapBlank:(CLLocationCoordinate2D)coordinate{
[self.mapView removeAnnotations:self.mapView.annotations];
//初始化标注类BMKPointAnnotation的实例
BMKPointAnnotation *annotation = [[BMKPointAnnotation alloc]init];
//设置标注的经纬度坐标
annotation.coordinate = coordinate;
/**
当前地图添加标注,需要实现BMKMapViewDelegate的-mapView:viewForAnnotation:方法
来生成标注对应的View
@param annotation 要添加的标注
*/
[self.mapView addAnnotation:annotation];
//设置当前地图的中心点
self.mapView.centerCoordinate = annotation.coordinate;
// 这里可以获取地理位置的经纬度
BMKReverseGeoCodeSearchOption *reverseGeoCodeOption = [[BMKReverseGeoCodeSearchOption alloc]init];
reverseGeoCodeOption.location = coordinate;
// 是否访问最新版行政区划数据(仅对中国数据生效)
reverseGeoCodeOption.isLatestAdmin = YES;
BOOL flag = [self.search reverseGeoCode: reverseGeoCodeOption];
if (flag) {
NSLog(@"逆geo检索发送成功");
} else {
NSLog(@"逆geo检索发送失败");
}
}
#pragma mark - BMKPoiSearchDelegate
/**
*返回POI搜索结果
*@param searcher 搜索对象
*@param poiResult 搜索结果列表
*@param errorCode 错误号,@see BMKSearchErrorCode
*/
-(void)onGetPoiResult:(BMKPoiSearch *)searcher result:(BMKPOISearchResult *)poiResult errorCode:(BMKSearchErrorCode)errorCode{
//BMKSearchErrorCode错误码,BMK_SEARCH_NO_ERROR:检索结果正常返回
if (errorCode == BMK_SEARCH_NO_ERROR) {
//在此处理正常结果
ZRLog(@"检索结果返回成功:%@",poiResult.poiInfoList);
[self.poiInfos removeAllObjects];
[self.poiInfos addObjectsFromArray:poiResult.poiInfoList];
[self.selectArr removeAllObjects];
for (int i = 0;i < self.poiInfos.count;i ++) {
BMKPoiInfo *point = self.poiInfos[i];
// 这个是定位之后获取的一个地址名字,方便搜索的时候用的
self.cityName = point.address;
// 计算距离
if (point.distance == 0) {
BMKMapPoint point1 = BMKMapPointForCoordinate(point.pt);
BMKMapPoint point2 = BMKMapPointForCoordinate(self.userLocation.location.coordinate);
CLLocationDistance distance = BMKMetersBetweenMapPoints(point1,point2);
point.distance = distance;
}
// 由于不能存逻辑值,而且不能用百度的模型,那么存字符串了
NSString *select = @"未选中";
if (i == 0) { // 默认第一个选中
self.selectedPoiInfo = point;
select = @"选中";
// 移动到地图选定的地址
[self.mapView removeAnnotations:self.mapView.annotations];
//初始化标注类BMKPointAnnotation的实例
BMKPointAnnotation *annotation = [[BMKPointAnnotation alloc]init];
//设置标注的经纬度坐标
annotation.coordinate = point.pt;
/**
当前地图添加标注,需要实现BMKMapViewDelegate的-mapView:viewForAnnotation:方法
来生成标注对应的View
@param annotation 要添加的标注
*/
[self.mapView addAnnotation:annotation];
//设置当前地图的中心点
self.mapView.centerCoordinate = annotation.coordinate;
// 由于搜索到的获取不到邮政编码,所以用系统框架,获取邮政编码
//根据经纬度获取省份城市
CLGeocoder *clGeoCoder = [[CLGeocoder alloc] init];
CLLocation *newLocation = [[CLLocation alloc]initWithLatitude:point.pt.latitude longitude:point.pt.longitude];
[clGeoCoder reverseGeocodeLocation:newLocation completionHandler: ^(NSArray *placemarks,NSError *error) {
for (CLPlacemark *placeMark in placemarks)
{
self.areaCode = placeMark.postalCode;
}
}];
}
[self.selectArr addObject:select];
}
[self.tableView reloadData];
}
else if (errorCode == BMK_SEARCH_AMBIGUOUS_KEYWORD) {
ZRLog(@"检索词有歧义");
} else {
ZRLog(@"其他检索结果错误码相关处理");
}
}
#pragma mark - UITableViewDataSource,UITableViewDelegate
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.poiInfos.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
MapListViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MapListViewCell"];
cell.poiInfo = self.poiInfos[indexPath.row];
cell.addrSelect = self.selectArr[indexPath.row];
if (indexPath.row == self.poiInfos.count) {
cell.showLine = NO;
}else{
cell.showLine = YES;
}
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 76;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
BMKPoiInfo *poiInfo = self.poiInfos[indexPath.row];
self.selectedPoiInfo = poiInfo;
for (int i = 0; i < self.selectArr.count; i ++) {
[self.selectArr replaceObjectAtIndex:i withObject:@"未选中"];
}
[self.selectArr replaceObjectAtIndex:indexPath.row withObject:@"选中"];
// 移动到地图选定的地址
[self.mapView removeAnnotations:self.mapView.annotations];
//初始化标注类BMKPointAnnotation的实例
BMKPointAnnotation *annotation = [[BMKPointAnnotation alloc]init];
//设置标注的经纬度坐标
annotation.coordinate = poiInfo.pt;
/**
当前地图添加标注,需要实现BMKMapViewDelegate的-mapView:viewForAnnotation:方法
来生成标注对应的View
@param annotation 要添加的标注
*/
[self.mapView addAnnotation:annotation];
//设置当前地图的中心点
self.mapView.centerCoordinate = annotation.coordinate;
//根据经纬度获取省份城市
CLGeocoder *clGeoCoder = [[CLGeocoder alloc] init];
CLLocation *newLocation = [[CLLocation alloc]initWithLatitude:self.selectedPoiInfo.pt.latitude longitude:self.selectedPoiInfo.pt.longitude];
[clGeoCoder reverseGeocodeLocation:newLocation completionHandler: ^(NSArray *placemarks,NSError *error) {
for (CLPlacemark *placeMark in placemarks)
{
self.areaCode = placeMark.postalCode;
}
}];
[self.tableView reloadData];
}
#pragma mark - Lazy loading
-(NSMutableArray<BMKPoiInfo *> *)poiInfos{
if (!_poiInfos) {
_poiInfos = [[NSMutableArray alloc]init];
}
return _poiInfos;
}
-(NSMutableArray *)selectArr{
if (!_selectArr) {
_selectArr = [[NSMutableArray alloc]init];
}
return _selectArr;
}
- (BMKLocationManager *)locationManager {
if (!_locationManager) {
//初始化BMKLocationManager类的实例
_locationManager = [[BMKLocationManager alloc] init];
//设置定位管理类实例的代理
_locationManager.delegate = self;
//设定定位坐标系类型,默认为 BMKLocationCoordinateTypeGCJ02
_locationManager.coordinateType = BMKLocationCoordinateTypeBMK09LL;
//设定定位精度,默认为 kCLLocationAccuracyBest
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//设定定位类型,默认为 CLActivityTypeAutomotiveNavigation
_locationManager.activityType = CLActivityTypeAutomotiveNavigation;
//指定定位是否会被系统自动暂停,默认为NO
_locationManager.pausesLocationUpdatesAutomatically = NO;
/**
是否允许后台定位,默认为NO。只在iOS 9.0及之后起作用。
设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。
由于iOS系统限制,需要在定位未开始之前或定位停止之后,修改该属性的值才会有效果。
*/
_locationManager.allowsBackgroundLocationUpdates = NO;
/**
指定单次定位超时时间,默认为10s,最小值是2s。注意单次定位请求前设置。
注意: 单次定位超时时间从确定了定位权限(非kCLAuthorizationStatusNotDetermined状态)
后开始计算。
*/
_locationManager.locationTimeout = 10;
}
return _locationManager;
}
- (BMKUserLocation *)userLocation {
if (!_userLocation) {
//初始化BMKUserLocation类的实例
_userLocation = [[BMKUserLocation alloc] init];
}
return _userLocation;
}
@end
网友评论