美文网首页
开发问题笔记(十九)

开发问题笔记(十九)

作者: Kevin_wzx | 来源:发表于2022-11-05 00:30 被阅读0次

目录

1.bbx司机端同一手机App新旧包覆盖运行错误
2.bbx司机端UILabel隐藏了还是会显示xib默认填写的内容“乘客”
3.计算机程序工作的过程
4.计算机基础知识
5.关闭当前页面系统侧滑效果
6.debug 与 release
7.iOS 系统16中开启开发者模式
8.iOS 开发界面调试工具(Lookin、Reveal)
9.代码开源编辑器工具(非 iOS )
10.iOS 图片存放3种方式
11.百度地图导航中添加自定义view
12.iPad 和 iPhone 开发的异同
13.好用的截图工具 Flameshot、搜索 Alfred
14.关闭App也能一直在后台定位

1.bbx司机端同一手机App新旧包覆盖运行错误

场景:在重构司机端的时候,运行司机端重构项目即重构包A在手机上安装A进行开发。有时候需要开发bbx之前那个项目即原来包B,在这个时候手机上不卸载bbx司机端A直接连接到电脑xcode跑起来安装了B,这个时候登录账号则会闪退到定位请求方法这个地方,原因是因为token为空值。这个就是因为新旧包覆盖的时候token不一样的原因产生。解决这个即可按照下面方法,在重写set和init方法中进行相关修改即可。

属性 重写set方法 BBXDriverInfo类 init 方法 应用1 应用2 不按照上面方法修改程序会闪退在这个地方 上面闪退相关定位方法详情

2.bbx司机端UILabel隐藏了还是会显示xib默认填写的内容“乘客”

场景:大概为有个条件就是如果订单是招虎类型订单则展示这个控件用A表示,就是在 xib 里面画的那个默认写了个乘客在那边的那个 zhaohutelLab 控件。现在bug是列表订单不是招虎订单也显示了这个乘客二字。但是呢代码这边在自定义cell中的模型赋值的时候判断是先隐藏这个控件A,再判断如果是招虎订单则展示这个控件A。感觉逻辑什么的没有问题,但是不知道为啥还是会显示这个乘客二字。

解决:
1.这个应该是cell复用的问题,所以在cell中模型赋值的时候判断对if和else都要判断。因为前面先写了隐藏A再判断招虎则显示A,但是else没判断,这样有可能系统会直接把以前招虎订单类型的cell拿来用。但是这边不知道为啥这个方法不可以,可能因为控制器中对cell没有进行复用的原因,所以这边采用第二个方法解决,具体看情况分析判断。
2.在xib中吧这个控件A的这个默认的乘客2字去掉就没有问题了,不过这个方法不好的就是去掉之后没有这个字,控件高度什么的自动缩起来了在xib布局的时候不太好操作,不过可以用先填上字布局好之后再去掉也可以。

问题bug图:非招虎订单不应该显示乘客两个字 xib画的zhaohutelLab 解决办法1:在cell中赋值判断if和else 解决办法2:去掉xib中默认的字 控制器中cell不复用所以可能对方法2影响了

3.计算机程序工作的过程

计算机程序工作的过程 编译

4.计算机基础知识

https://mp.weixin.qq.com/s/GdVraiuDj3w21Wu-ofZxCA

计算机基础知识

5.关闭当前页面系统侧滑效果

相关链接:https://blog.csdn.net/u010960265/article/details/82977681

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;//关闭系统左滑手势
}
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    self.navigationController.interactivePopGestureRecognizer.enabled = YES;//开放侧滑,不影响其他页面
}

6.debug 与 release

  • 概念详解

1.Release 是发行版本,比 Debug 版本有一些优化,文件比 Debug 文件小;Debug 是调试版本,包括的程序信息更多。

2.Debug 和 Release 连接调用两个不同的底层库,两者的编译方式不一样。Debug 阶段有问题,Release 编译能通过也是有 bug 的。

3.只有 Debug 版的程序才能设置断点、单步执行、使用 TRACE/ASSERT 等调试输出语句。Release 不包含任何调试信息,所以体积小、运行速度快。

相关链接:
https://blog.csdn.net/myyllove/article/details/84982349
https://juejin.cn/post/6844903524359208974

  • 一些两者不同的调试技巧

1.默认工程一致是 Release 模式,Release 模式默认会编译 nslog 这行代码,发布的时候工程也必须是 Release 模式。

2.Debug 模式是不会编译 nslog 这行代码,但是如果增加一个全局的宏就可以编译,这个宏如下:(中间还可以有 else 来设置 Release 情况,举例如下图)

#ifdef DEBUG

//这里写 nslog 的代码

#endif

如果是在 Debug 模式下,这个宏中间的代码是会编译执行的

3.如何在开发过程中切换 Debug 模式和 Release 模式呢:product –> Scheme –> Edit Scheme -> Info –> Build Configuration 切换 Debug 和 Release 模式。

Debug 和 Release 代码举例:

#ifdef DEBUG
#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define DLog(...)
#endif
Debug 和 Release 代码举例 Debug 和 Release 代码举例 Debug 和 Release 切换方式
  • bbx 司机端实际场景举例

场景:测试2部手机,A 手机安装蒲公英打的测试包,B 手机直接连接电脑 Xcode 跑起来安装测试环境包。在后台系统测试环境关闭验证上传核酸照片开关,前端手机 App 点击报班按钮则不需要弹框核酸页面来上传,都是测试环境,A 不弹框核酸页面 B 有弹框,一直纳闷找不到原因,通过调试发现如下图代码有写了一段 Debug 测试代码1。原因就是 A 是打包上传到蒲公英来安装,因为打包的时候设置的是 Release,下图代码走红框2里面的,即后台返回的值 NO,而 B 通过 Xcode 跑起来安装,设置的是 Debug,所以 B 这边代码一直会走下图红框1里面的代码即核酸字段一直都是 YES,虽然后台返回的是 NO,但是都走 Debug 的代码所以 A 不弹 B 弹。prevention_test 是判断是否要上传核酸健康码的字段。

说明:
1.通常情况下打包给测试都是打 Debug,上线才会打 Release,打包的时候需要手动切换。而 bbx 司机端测试环境和灰度环境、正式环境点开这边设置的会看到默认都是 Release,bbx 司机端这边只是将接口环境那边设置改一下表示环境的数字来切换环境,打包的不动他,也就是给测试的包也是 Release。

2.我们没有对测试正式环境等与 Debug、Release 关联,那么就会产生各种组合比如测试环境 Release 包,测试环境 Debug 包等,这个会有影响,比如有些库只在 Debug 安装的,装了 Release 包可能就无法用会产生 bug。

3.bbx 司机端这边 bug 的解决方法就是:直接将 Debug 那段代码去掉用后台返回的字段数据,估计原先 App 这样设置就是为了图方便所以打包那个都直接用 Release。

bbx 司机端中举例,核酸字段 Debug 为 YES,Release 用后台返回的值 如果核酸字段为YES则需要上传核酸,为NO则不需要上传 BBXFYManager 类,核酸字段为 prevention_test bbx 环境切换 - 表示环境的数字来切换环境 bbx项目中运行 Run 的时候默认设置 Debug bbx项目中打包 Archive 的时候默认设置 Release;一般打包的时候测试环境用 Debug,生产正式环境用 Release;这边都是用 Release 可能为了方便

7. iOS 系统16中开启开发者模式

场景:苹果手机注册过 bbx App 的 UDID 了,在蒲公英安装测试环境的 bbx 司机端会报错:“需要启用开发者模式”。原因是苹果手机升级系统到最新的16系统,所以会有这个安全保护问题,在手机设置里面找到隐私与安全再选择开发者模式进行开启就可以正常安装 App。

安装测试环境的bbx司机端失败提示:需要启用开发者模式 设置 -> 隐私与安全 -> 开发者模式 启用开发者模式

8.iOS 开发界面调试工具(Lookin、Reveal)

  • Lookin:

https://lookin.work/?continueFlag=f3def538325030e402a04a4a433237e3
https://juejin.cn/post/6844904190393712647

  • Reveal:

https://revealapp.com/
http://events.jianshu.io/p/1bc87f447c33

9.代码开源编辑器工具(非 iOS )

https://mp.weixin.qq.com/s/aTw4poDMgvzpGGKG1MLmnA

10.iOS 图片存放3种方式

https://juejin.cn/post/6844903978262773774

11.百度地图导航中添加自定义view

如下图,可以在导航中添加自定义view,比如按钮、底部订单面板等等;可以看到下图有添加面板和没有面板的效果。需要注意的是进入导航中,这个导航页是地图的一个view不是控制器,而高德地图导航页是个控制器,在做页面跳转啥的时候需要注意考虑这个。

没有加面板 没有加面板-点击一下地图效果,可以点继续导航恢复到上面效果 有添加面板页面

百度地图导航管理类核心代码:(部分回调啥的删减)

#import "BBXMapNaviManager.h"
#import "BNaviModel.h"
#import "SKSpeechManager.h"
#import "LocationManager.h"
#import <BaiduMapAPI_Utils/BMKGeometry.h>
#import <CoreLocation/CoreLocation.h>
#import "BNaviService.h"
#import <ReactiveObjC/ReactiveObjC.h>
#import "BBXBillViewController.h"
#import "YHRootNavigationVController.h"
#import "BBXCallUtil.h"
#import "NetworkClient+Driver.h"
#import "UIView+BBX.h"
#import "NetworkClient+Order.h"
#import "Request.h"
#import "OrderInfo.h"
#import "NSString+YYAdd.h"
#import "DeviceTypeManager.h"
#import "BBXMapNavigationPopupView.h"
#import "BNNaviMessageInfo.h"
#import "AppDelegate+TCP.h"
#import "BBXAudioManager.h"

#define GRADIENTSLIDER_HEIGHT 62

typedef NS_ENUM(NSInteger, BBXRoutePlanType) {
    BBXRoutePlanTypeInside  = 0,//内置导航
    BBXRoutePlanTypeGaoDe   = 1,//高德地图
    BBXRoutePlanTypeBaidu   = 2,//百度地图
    BBXRoutePlanTypeTencent = 3,//腾讯地图
    BBXRoutePlanTypeApple   = 4,//苹果地图
};

@interface BBXMapNaviManager () <BNNaviUIManagerDelegate,BNNaviRoutePlanDelegate,BBBXMapNavigationPopupViewDelegate>
@property (nonatomic, strong) UIButton *coverUpBtn;//遮住顶部导航里箭头的视图
@property (nonatomic, strong) UIButton *exitMapButton;//退出导航按钮
@property (nonatomic, strong) BBXMapNavigationPopupView *mapNavigationPopupView;//导航信息弹窗
@property (nonatomic, strong) NSTimer *dataTimer;
@property (nonatomic, strong) RACDisposable *naviDisposable;
@property (nonatomic, strong) RACSignal *naviSignal;
@property (nonatomic, assign) NSInteger messageType; //接收到的后台通知类型(当后台操作乘客上车时类型为5,如果是公式计价单,要开启实时计价)
@property (nonatomic, assign) BOOL isRefreshFinishBack;//是否在当前页面接收订单刷新通知(如点击知道了)以后返回地图页
@property (nonatomic, strong) Multiple *multipleModel;
@property (nonatomic, assign) NSInteger viewTag;
@end

@implementation BBXMapNaviManager

+ (instancetype)shareManager{
    static BBXMapNaviManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[BBXMapNaviManager alloc] init];
    });
    return manager;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        self.messageType = -1; //初始化为无效值
    }
    return self;
}

#pragma mark -- 开始导航
//开始导航
- (void)beginMapNaviWithOrderViewModel:(OrderViewModel *)orderViewModel {
    [SVProgressHUD show];
    //设置延迟消失机制,避免转圈圈不消失
    [SVProgressHUD dismissWithDelay:3];
    self.orderViewModel = orderViewModel;
    self.multipleModel = nil;
    if (_naviDisposable) {
        [_naviDisposable dispose];
    }
    //获取导航vc
    UIViewController *oldNaviViewController = [BNaviModel getInstance].naviViewController;
    _naviSignal = [[RACObserve([BNaviModel getInstance], naviViewController) filter:^BOOL(id  _Nullable value) {
        return value != nil && value != oldNaviViewController;
    }] take:1];
    @weakify(self);
    _naviDisposable = [_naviSignal subscribeNext:^(id  _Nullable x) {
        //直到[BNaviModel getInstance].naviViewController有值时才开始绑定视图事件
        @strongify(self);
        [self bindViewAction];
    }];
    CLLocationDegrees dest_lat = 0;//纬度
    CLLocationDegrees dest_lng = 0;//经度
    OrderListModel *orderListModel = self.orderViewModel.orderModel;
    //终点坐标经纬度
    if (orderListModel.order_status == 6 || orderListModel.order_status == Order_state_sended) {//接客
        dest_lat = orderListModel.start_lat;
        dest_lng = orderListModel.start_lng;
    } else {//送客
        dest_lat = orderListModel.end_lat;
        dest_lng = orderListModel.end_lng;
    }
    //导航起点终点经纬度
    CLLocationCoordinate2D startCoor = [LocationManager shareManager].location.coordinate;//导航起点
    CLLocationCoordinate2D endCoor = CLLocationCoordinate2DMake(dest_lat, dest_lng);//导航终点
    //将经纬度坐标转换为投影后的直角地理坐标
    BMKMapPoint startPoint = BMKMapPointForCoordinate(startCoor);
    BMKMapPoint endPoint = BMKMapPointForCoordinate(endCoor);
    //计算指定两点之间的距离
    float distance= BMKMetersBetweenMapPoints(startPoint,endPoint);
    if (distance < 100) {
        NSString *spekStr = @"距离太近,不能导航";
        [BBXAudioManager sharedAudioManager].spekType = @"0";
        [[AppDelegate shareAppDelegate] judgeVoicePlayWithModel:nil Speking:spekStr spekType:[BBXAudioManager sharedAudioManager].spekType];
        [SKToast showWithText:spekStr];
        [SVProgressHUD dismiss];
        return;
    }
    //显示路线规划
    [self showRoutePlanSheetWithStartCoor:startCoor endCoor:endCoor];
}

//小包车-开始导航
- (void)beginMapNaviWithMultipleModel:(Multiple *)multipleModel orderViewModel:(OrderViewModel *)orderViewModel viewTag:(NSInteger)viewTag {
    
}

#pragma mark -- RAC绑定视图事件
//绑定视图事件
- (void)bindViewAction {
    UIViewController *naviViewController = [BNaviModel getInstance].naviViewController;
    @weakify(self);
    [[naviViewController rac_signalForSelector:@selector(viewDidLoad)] subscribeNext:^(RACTuple * _Nullable x) {
        @strongify(self);
        [self map_viewDidload];
    }];
    [[naviViewController rac_signalForSelector:@selector(viewWillAppear:)] subscribeNext:^(RACTuple * _Nullable x) {
        @strongify(self);
        [self map_viewWillAppear];
    }];
    [[naviViewController rac_signalForSelector:@selector(viewDidAppear:)] subscribeNext:^(RACTuple * _Nullable x) {
        @strongify(self);
        [self map_viewDidAppear];
    }];
    [[naviViewController rac_signalForSelector:@selector(viewWillDisappear:)] subscribeNext:^(RACTuple * _Nullable x) {
        @strongify(self);
        [self map_viewWillDisappear];
    }];
}

#pragma mark -- 视图响应
- (void)map_viewDidload {
    
    self.isRefreshFinishBack = NO;
    if (!self.orderViewModel) return;
    //订单刷新通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshEvent) name:@"BBXRefreshOrderDataNotification" object:nil];
}

- (void)map_viewWillAppear {
    UIView *superView = [BNaviModel getInstance].naviViewController.view;
    //移除百度地图导航底部视图(如:剩余xx公里 xx分钟、退出、更多等视图)和顶部部分视图
    [self dealNativeViewInSuperView:superView];
}

//在viewDidAppear添加退出导航按钮避免退出导航按钮动画太过生硬
- (void)map_viewDidAppear {
    
    [SVProgressHUD dismiss];
    //创建界面
    [self createView];
    //启动5秒刷新1次订单的定时器
    if(!_dataTimer && self.orderViewModel.orderModel.showInGongshijija) {
        NSInteger timeInterval = 5;
        _dataTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(refreshEvent) userInfo:nil repeats:YES];
    }
    //公式计价并且乘客已上车,则刷新价格
    if (self.orderViewModel.orderModel.showInGongshijija &&
        self.orderViewModel.orderModel.order_status >= Order_state_get_on) {
        @weakify(self);
        [OrderInfo shareManager].priceBlock = ^(NSDictionary *priceDict) {
            @strongify(self);
            if (!self) return;
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.orderViewModel refreshPrice];
                self.mapNavigationPopupView.orderViewModel = self.orderViewModel;//更新数据
            });
        };
    }
}

- (void)map_viewWillDisappear {
    
    if (self.exitMapButton) {
        [self.exitMapButton removeFromSuperview];
        self.exitMapButton = nil;
    }
    if (self.coverUpBtn) {
        [self.coverUpBtn removeFromSuperview];
        self.coverUpBtn = nil;
    }
    if (self.mapNavigationPopupView) {
        [self.mapNavigationPopupView removeFromSuperview];
        self.mapNavigationPopupView = nil;
    }
}

#pragma mark -- 创建界面
//创建界面
- (void)createView {
    
    UIWindow *window = [BNaviModel getInstance].naviViewController.view.window;
    //添加地图导航弹窗
    [window addSubview:self.mapNavigationPopupView];//添加底部订单面板页面
    if (self.multipleModel) {
        [self.mapNavigationPopupView setViewModel:self.orderViewModel multipleModel:self.multipleModel viewTag:self.viewTag];
        
    } else {
        self.mapNavigationPopupView.orderViewModel = self.orderViewModel;
    }
    //添加退出导航按钮
    [window addSubview:self.exitMapButton];
    //添加顶部遮住导航里箭头的视图
    [window addSubview:self.coverUpBtn];
}

//导航信息弹窗
- (BBXMapNavigationPopupView *)mapNavigationPopupView {
    if (!_mapNavigationPopupView) {
        _mapNavigationPopupView = [[BBXMapNavigationPopupView alloc] initWithFrame:CGRectMake(0, ([UIScreen mainScreen].bounds.size.height - 190), [UIScreen mainScreen].bounds.size.width, 205)];
        _mapNavigationPopupView.delegate = self;
    }
    return _mapNavigationPopupView;
}

//退出导航按钮
- (UIButton *)exitMapButton {
    if (!_exitMapButton) {
        UIImage * image = [UIImage imageNamed:@"BBXMapNaviManager_exit"];
        //获取状态栏的高度
        CGFloat statusHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
        CGFloat x = [UIScreen mainScreen].bounds.size.width - 15 - 50;
        CGFloat y = 30 + statusHeight;
        
        _exitMapButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _exitMapButton.frame = CGRectMake(x, y, 50, 50);
        [_exitMapButton setImage:image forState:UIControlStateNormal];
        [_exitMapButton addTarget:self action:@selector(exitMap) forControlEvents:UIControlEventTouchUpInside];
    }
    return _exitMapButton;
}

//遮住顶部导航里箭头的视图
- (UIButton *)coverUpBtn {
    if (!_coverUpBtn) {
        _coverUpBtn = [[UIButton alloc]init];
        CGFloat statusHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
        CGFloat y = 7 + statusHeight;
        _coverUpBtn.backgroundColor = [UIColor clearColor];
        _coverUpBtn.frame = CGRectMake(10, y, 98, 98);
        [_coverUpBtn addTarget:self action:@selector(coberBtnClick) forControlEvents:UIControlEventTouchUpInside];
    }
    return _coverUpBtn; 
}

- (void)coberBtnClick {
    NSLog(@"123");
}

#pragma mark -- 通知响应函数
- (void)refreshAction {
    self.isRefreshFinishBack = YES;
}

//订单刷新通知响应函数
- (void)refreshEvent{

    if (!self.orderViewModel) return;
    __weak typeof(self)weakSelf = self;
    //获取调度id
    [[NetworkClient sharedInstance] requestOrderListWithCompleteBlock:^(NSDictionary *responseObject) {
        NSArray *IDArray = responseObject[@"list"];
        NSMutableDictionary *paraDict;
        if (!IDArray || IDArray.count == 0) return;
        paraDict = [responseObject mutableCopy];
        [paraDict setObject:[[NSMutableArray alloc] init] forKey:@"complationArr"];
        //根据调度id请求订单列表
        [Request requestGetOrderListsWithDict:paraDict AndComplation:^(NSDictionary *dict) {
            
            if (!dict || [dict[@"status"] integerValue] != 0) return;
            if (isNullArray(dict[@"list"])) return;
            NSArray <NSDictionary *> *listArr = dict[@"list"];
            if (listArr.count == 0) return;
            NSArray <OrderListModel *>*orderArr = [[NSArray alloc] init];
            NSMutableArray * mutArr = [[NSMutableArray alloc] init];
            for (NSDictionary * dic in listArr) {
                NSArray * arr = dic[@"order_arr"];
                if (arr != nil) {
                    [mutArr addObjectsFromArray:arr];
                }
            }
            orderArr = [mutArr copy];
            if (orderArr.count == 0) return;
            //更新当前订单model信息
            OrderListModel *oldOrderModel = self.orderViewModel.orderModel;
            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"order_id == %@", oldOrderModel.order_id];
            OrderListModel *newOrderModel = [[orderArr filteredArrayUsingPredicate:predicate] firstObject];
            if (self.messageType == 5) {//后台操作乘客上车,判断是否是公式计价的订单,如果是的话要开启实时计价
                if (newOrderModel.order_type == OrderType_city ||
                    newOrderModel.order_type == OrderType_DesignatedDriver){
                    //市内公式计价(代驾的计价方式与市内一样)
                    BOOL isInCityGongshi = ((newOrderModel.order_type == OrderType_city || newOrderModel.order_type == OrderType_DesignatedDriver) && newOrderModel.calc_type == 1);
                    //城际包车公式计价
                    BOOL isCharteredGongshi = newOrderModel.bussiness_type != 0 && newOrderModel.order_type == OrderType_CarChartered;
                    if (isInCityGongshi) {
                        //如果是市内公式计价,再判断订单id是否是要计价的订单id
                        newOrderModel.showInGongshijija = [newOrderModel.order_id isEqualToString:[BBXDriverInfo shareManager].onCarOrder_id];
                    } else if (isCharteredGongshi) {
                        newOrderModel.showInGongshijija = YES;
                    }
                   //启动5秒刷新1次订单的定时器
                    if(!weakSelf.dataTimer) {
                      NSInteger timeInterval = 5;
                       weakSelf.dataTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(refreshEvent) userInfo:nil repeats:YES];
                   }
                } else {
                   newOrderModel.showInGongshijija = oldOrderModel.showInGongshijija;
                }
            } else {
                newOrderModel.showInGongshijija = oldOrderModel.showInGongshijija;
            }
            self.orderViewModel = [[OrderViewModel alloc] initWithOrderModel:newOrderModel];
            //根据更新后的当前订单model信息,更新右滑控、地址信息、订单类型等界面信息
            dispatch_async(dispatch_get_main_queue(), ^{
                self.mapNavigationPopupView.orderViewModel = self.orderViewModel;
            });
        }];
    }];
}

#pragma mark -- 当前正在导航的订单id
- (NSString *)currentNaviOrderId {
    if (self.orderViewModel) {
        return self.orderViewModel.orderModel.order_id;
    }
    return nil;
}

#pragma mark -路线规划- 
//路线规划
- (void)showRoutePlanSheetWithStartCoor:(CLLocationCoordinate2D)startCoor endCoor:(CLLocationCoordinate2D)endCoor {
    [self actionRoutePlanWithStartCoor:startCoor endCoor:endCoor type:BBXRoutePlanTypeInside];
}

//根据起点和终点坐标,重新规划路线
- (void)actionRoutePlanWithStartCoor:(CLLocationCoordinate2D)startCoor endCoor:(CLLocationCoordinate2D)endCoor type:(BBXRoutePlanType)type {
    
    //App内导航
    if (type == BBXRoutePlanTypeInside) {//内置导航
        //路径规划节点--起点
        BNRoutePlanNode *startNode = [[BNRoutePlanNode alloc] init];
        startNode.pos = [[BNPosition alloc] init];
        startNode.pos.eType = BNCoordinate_BaiduMapSDK;//坐标系类型
        startNode.pos.x = startCoor.longitude;
        startNode.pos.y = startCoor.latitude;
        //路径规划节点--终点
        BNRoutePlanNode *endNode = [[BNRoutePlanNode alloc] init];
        endNode.pos = [[BNPosition alloc] init];
        endNode.pos.eType = BNCoordinate_BaiduMapSDK;
        endNode.pos.x = endCoor.longitude;
        endNode.pos.y = endCoor.latitude;

        [BNaviService_RoutePlan setDisableOpenUrl:YES];//禁用跳转到百度地图的原因是不会触发代理方法,不好控制
        /*
         发起算路
         eMode     算路方式,定义见BNRoutePlanMode
         naviNodes 算路节点数组,起点、途经点、终点按顺序排列,节点信息为BNRoutePlanNode结构
         naviTime  发起算路时间,用于优化算路结果,可以为nil
         delegate  算路委托,用于回调
         userInfo  用户需要传入的参数
        */
        [BNaviService_RoutePlan startNaviRoutePlan:BNRoutePlanMode_Recommend naviNodes:@[startNode,endNode] time:nil delegete:self userInfo:nil];//发起路径规划
        return;
    }
}

#pragma mark -- 隐藏百度地图导航的底部的视图
//移除百度地图导航底部视图(如:剩余xx公里 xx分钟、退出、更多等视图)和顶部部分视图
- (void)dealNativeViewInSuperView:(UIView *)superView {
    
    NSString *className = NSStringFromClass(superView.class);
    if ([className isEqualToString:@"BNOpenKitTopGuideView"]) {
        /*
         隐藏掉BNOpenKitTopGuideView视图上的BNaviNextTurnView和BNaviStateIconsStackView视图,
         这两个视图的位置换成了放退出按钮,不移除掉的话会和百度的随后转弯、GPS信号弱、没声音图标叠在一起
         */
        for (UIView * view in superView.subviews) {
            if ([NSStringFromClass(view.class) isEqualToString:@"BNaviStateIconsStackView"] ||
                [NSStringFromClass(view.class) isEqualToString:@"BNaviNextTurnView"]) {
                [view removeFromSuperview];
            }
        }
        return;
    }
    
    if (superView.subviews.count == 0) {
        return;
    }

    for (UIView *view in superView.subviews) {
        [self dealNativeViewInSuperView:view];
    }
}

#pragma mark -- 按钮响应函数
//退出导航响应函数
- (void)exitMap {
    if (!BNaviService_UI.isInNaviPage) return;
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [[BNaviModel getInstance] exitNavi];
        if (@available(iOS 13.0, *)) {
            [self.exitMapButton removeFromSuperview];
            [self.coverUpBtn removeFromSuperview];
            [[BNaviModel getInstance].naviViewController dismissViewControllerAnimated:NO completion:nil];
        } else {
            [[BNaviModel getInstance].naviViewController dismissViewControllerAnimated:YES completion:nil];
        }
        for (UIView *sub in [UIApplication sharedApplication].keyWindow.subviews) {
            if ([sub isKindOfClass:NSClassFromString(@"PopAnimationV")]) {
                [sub removeFromSuperview];
            }
            if ([sub isKindOfClass:NSClassFromString(@"ChoosePopupView")]) {
                [sub removeFromSuperview];
            }
            if ([sub isKindOfClass:NSClassFromString(@"BBXPopAlertShadowView")]) {
                [sub removeFromSuperview];
            }
        }
    });
    
    if (self.isRefreshFinishBack == YES) {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"SignoutMapViewRefreshDataNotification" object:nil userInfo:nil];//在导航页的时候进行订单推送点击知道了停留当前页面,点击退出导航后通知地图页刷新
    }
    self.isRefreshFinishBack == NO;
}

#pragma mark -导航路线规划代理方法(BNNaviRoutePlanDelegate)-
//算路成功回调
- (void)routePlanDidFinished:(NSDictionary *)userInfo {
    NSLog(@"算路成功");
    [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
    //设置为外部gps导航模式
    [BNaviService_Location setGpsFromExternal:YES];
    //显示导航UI
    [BNaviService_UI showPage:BNaviUI_NormalNavi delegate:self extParams:nil];
}

//算路失败回调
- (void)routePlanDidFailedWithError:(NSError *)error andUserInfo:(NSDictionary *)userInfo {
    NSLog(@"算路失败");
    NSString *showTest = @"算路失败";
    showTest = @"路径规划失败,请重新规划";
    
    switch ([error code]%10000)
    {
        case BNAVI_ROUTEPLAN_ERROR_LOCATIONFAILED:
            NSLog(@"暂时无法获取您的位置,请稍后重试");
            showTest = @"暂时无法获取您的位置,请稍后重试";
            break;
        case BNAVI_ROUTEPLAN_ERROR_ROUTEPLANFAILED:
            NSLog(@"无法发起导航");
            showTest = @"无法发起导航";
            break;
        case BNAVI_ROUTEPLAN_ERROR_LOCATIONSERVICECLOSED:
            NSLog(@"定位服务未开启,请到系统设置中打开定位服务。");
            showTest = @"定位服务未开启,请到系统设置中打开定位服务。";
            break;
        case BNAVI_ROUTEPLAN_ERROR_NODESTOONEAR:
            NSLog(@"距离太近, 不能导航");
            showTest = @"距离太近, 不能导航";
            break;
        default:
            NSLog(@"算路失败");
            break;
    }
    NSString *spekStr = showTest;
    [BBXAudioManager sharedAudioManager].spekType = @"0";
    [[AppDelegate shareAppDelegate] judgeVoicePlayWithModel:nil Speking:spekStr spekType:[BBXAudioManager sharedAudioManager].spekType];
    [SKToast showWithText:spekStr];
}

//算路取消回调
- (void)routePlanDidUserCanceled:(NSDictionary*)userInfo {
    NSLog(@"算路取消");
}

//退出导航回调
- (void)onExitNaviUI:(NSDictionary*)extraInfo {
    [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
    NSLog(@"退出导航");
}

//退出导航声明页面回调
- (void)onExitexitDeclarationUI:(NSDictionary*)extraInfo {
    NSLog(@"退出导航声明页面");
}

//退出导航页面
- (void)onExitPage:(BNaviUIType)pageType extraInfo:(NSDictionary *)extraInfo {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    if (_dataTimer) {
        [_dataTimer invalidate];
        _dataTimer = nil;
    }
    
    if (_naviDisposable) {
        [_naviDisposable dispose];
        _naviDisposable = nil;
    }
    _naviSignal = nil;
    self.orderViewModel = nil;
}

#pragma mark -- 释放导航服务
//释放导航服务
- (void)releaseService {
    [BNaviService_Instance stopServices];
    [BNaviService releaseInstance];
    //不知道怎么回事,stopServices和ReleaseInstance之后竟然还没有停止,加入这个方法就可以了
    [BNaviService_Location stopUpdate];
}

-(void)dealloc {
    
    [[NSNotificationCenter defaultCenter]removeObserver:self];
}

#pragma mark -- 智能调度
//是否从接客地图智能调度订单跳过来
- (void)setIsDiaoduPickMapJump:(BOOL)isDiaoduPickMapJump {
    _isDiaoduPickMapJump = isDiaoduPickMapJump;
}

//开始导航(智能调度)
- (void)diaoduBeginMapNaviWithOrderArray:(NSMutableArray *)orderArray {
    
    [SVProgressHUD show];
    //设置延迟消失机制,避免转圈圈不消失
    [SVProgressHUD dismissWithDelay:3];

    OrderListModel *model = [[OrderListModel alloc]init];
    if (orderArray.count>0) {
        model = orderArray.firstObject;//刚进入导航的时候默认去接第一个乘客
    }
    OrderViewModel *orderViewModel = [[OrderViewModel alloc] initWithOrderModel:model];
    
    
    self.orderViewModel = orderViewModel;
    self.multipleModel = nil;
    if (_naviDisposable) {
        [_naviDisposable dispose];
    }
    //获取导航vc
    UIViewController *oldNaviViewController = [BNaviModel getInstance].naviViewController;
    _naviSignal = [[RACObserve([BNaviModel getInstance], naviViewController) filter:^BOOL(id  _Nullable value) {
        return value != nil && value != oldNaviViewController;
    }] take:1];

    @weakify(self);
    _naviDisposable = [_naviSignal subscribeNext:^(id  _Nullable x) {
        //直到[BNaviModel getInstance].naviViewController有值时才开始绑定视图事件
        @strongify(self);
        [self bindViewAction];
    }];
    
    CLLocationDegrees dest_lat = 0;//纬度
    CLLocationDegrees dest_lng = 0;//经度
    OrderListModel *orderListModel = self.orderViewModel.orderModel;
    //终点坐标经纬度
    if (orderListModel.order_status == 6 || orderListModel.order_status == Order_state_sended) {//接客 (6不知道是啥)

        if (orderListModel.order_type == OrderType_Bus) {// 快线-接客
            if ([orderListModel.locations.start.area_level isEqualToString:@"1"] || [orderListModel.locations.start.area_level isEqualToString:@"3"]) {//详细地址
                dest_lat = orderListModel.start_lat;
                dest_lng = orderListModel.start_lng;
            } else  {//站点
                
                NSDictionary *dataDict = [NSDictionary dictionaryWithJsonString:orderListModel.locations.start.station_location];
                if([dataDict isKindOfClass:[NSDictionary class]]) {
                    CLLocationDegrees lat = [dataDict[@"lat"] doubleValue];
                    CLLocationDegrees lng = [dataDict[@"lng"]doubleValue];
                    dest_lat = lat;
                    dest_lng = lng;
                }else{
                    CLLocationDegrees lat = [orderListModel.locations.start.lat doubleValue];
                    CLLocationDegrees lng = [orderListModel.locations.start.lng doubleValue];
                    dest_lat = lat;
                    dest_lng = lng;
                }
            }
        } else {//快线除外
            
            if (orderListModel.order_type == OrderType_DesignatedDriver) {//代驾
                dest_lat = orderListModel.end_lat;
                dest_lng = orderListModel.end_lng;
            } else {
                dest_lat = orderListModel.start_lat;
                dest_lng = orderListModel.start_lng;
            }
        }
    } else {//送客
        
        if (orderListModel.order_type == OrderType_Bus) {// 快线-送客
            if ([orderListModel.locations.end.area_level isEqualToString:@"2"] || [orderListModel.locations.end.area_level isEqualToString:@"3"]) {
                dest_lat = orderListModel.end_lat;
                dest_lng = orderListModel.end_lng;
            } else  {
                
                NSDictionary *dataDict = [NSDictionary dictionaryWithJsonString:orderListModel.locations.end.station_location];//{"lat":"24.579875","lng":"118.101234"}
                if([dataDict isKindOfClass:[NSDictionary class]]) {
                    CLLocationDegrees lat = [dataDict[@"lat"] doubleValue];
                    CLLocationDegrees lng = [dataDict[@"lng"]doubleValue];
                    dest_lat = lat;
                    dest_lng = lng;
                }else{
                    CLLocationDegrees lat = [orderListModel.locations.end.lat doubleValue];
                    CLLocationDegrees lng = [orderListModel.locations.end.lng doubleValue];
                    dest_lat = lat;
                    dest_lng = lng;
                }
            }
        } else {
            
            dest_lat = orderListModel.end_lat;
            dest_lng = orderListModel.end_lng;
        }
    }
    //导航起点终点经纬度
    CLLocationCoordinate2D startCoor = [LocationManager shareManager].location.coordinate;//导航起点
    CLLocationCoordinate2D endCoor = CLLocationCoordinate2DMake(dest_lat, dest_lng);//导航终点
    //将经纬度坐标转换为投影后的直角地理坐标
    BMKMapPoint startPoint = BMKMapPointForCoordinate(startCoor);
    BMKMapPoint endPoint = BMKMapPointForCoordinate(endCoor);
    //计算指定两点之间的距离
    float distance= BMKMetersBetweenMapPoints(startPoint,endPoint);
    if (distance < 100) {
        //【加交警处理】  [SKSpeechManager speakToast:@"距离太近,不能导航"];
        NSString *spekStr = @"距离太近,不能导航";
        [BBXAudioManager sharedAudioManager].spekType = @"0";
        [[AppDelegate shareAppDelegate] judgeVoicePlayWithModel:nil Speking:spekStr spekType:[BBXAudioManager sharedAudioManager].spekType];
        [SKToast showWithText:spekStr];
        [SVProgressHUD dismiss];
        return;
    }
    
    //显示路线规划
    [self showRoutePlanSheetWithStartCoor:startCoor endCoor:endCoor];
}

//更换终点重新算路发起导航
- (void)updateMapNaviWithOrderViewModel:(OrderViewModel *)orderViewModel {
    
    //[self reNaviToEndAddr];
    //终点经纬度坐标
    OrderListModel *orderListModel = orderViewModel.orderModel;
    CLLocationDegrees dest_lat = orderListModel.start_lat;
    CLLocationDegrees dest_lng = orderListModel.start_lng;
    CLLocationCoordinate2D endCoor = CLLocationCoordinate2DMake(dest_lat, dest_lng);

    //路径规划节点
    BNRoutePlanNode *endNode = [[BNRoutePlanNode alloc] init];
    endNode.pos = [[BNPosition alloc] init];//位置原始坐标
    endNode.pos.eType = BNCoordinate_BaiduMapSDK;//坐标系类型
    endNode.pos.x = endCoor.longitude;
    endNode.pos.y = endCoor.latitude;
    dispatch_async(dispatch_get_main_queue(), ^{
        [[BNaviModel getInstance] resetNaviEndPoint:endNode];//导航中改变终点调用接口
    });
    WeakSelf
    dispatch_async(dispatch_get_main_queue(), ^{
        [weakSelf.orderViewModel refreshPrice];
        weakSelf.mapNavigationPopupView.orderViewModel = orderViewModel;//更新数据
    });
}

@end

12.iPad 和 iPhone 开发的异同

https://www.jianshu.com/p/059c6d19585f

13.好用的截图工具 Flameshot、搜索 Alfred

Flameshot

下载链接: https://pan.baidu.com/s/16dzGDCKnndXOj_YXX_wjlQ 提取码: 6699
相关链接:https://mp.weixin.qq.com/s/XOmzmcCdd7WhfWgYQwPNBA

Alfred

下载链接:https://pan.baidu.com/s/1hzH7nRQTlx_hxeYwHSzeRQ?pwd=9696 提取码: 9696
相关链接:https://www.jianshu.com/p/6d08c95b7f36

14.关闭App也能一直在后台定位(未修改)

https://mobileoop.com/getting-location-updates-for-ios-7-and-8-when-the-app-is-killedterminatedsuspended

相关文章

网友评论

      本文标题:开发问题笔记(十九)

      本文链接:https://www.haomeiwen.com/subject/rxtutdtx.html