iOS 技巧

开发问题笔记(十七)

2022-03-30  本文已影响0人  Kevin_wzx

目录

1.获取某天/月/年的开始时间和结束时间
2.从时间字符串中获取“年-月-日-时-分-秒”
3.获取当前控制器类扩展
4.xib写的的控件通过更新约束来更新布局
5.UITableViewStyleGrouped样式的tableview顶部有距离
6.tableView的空数据占位图可以用_tableView.backgroundView
7.iOS MVVM的理解与分析
8.百度地图定位权限没有添加完整导致无法定位
9.runtime的应用(百度地图弹框的模态跳转方式设置)

1.获取某天/月/年的开始时间和结束时间

相关链接:
https://blog.csdn.net/lwq421336220/article/details/16335095
https://blog.csdn.net/yaoliangjun306/article/details/51553821

//获取当前时间
- (void)getCurrentTime {
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"YYYY-MM-dd"];
    NSDate *dateNow = [NSDate date];
    NSString *currentTimeString = [formatter stringFromDate:dateNow];//获取当前时间
    [self getMonthBeginAndEndWith:dateNow];
    [self getYearBeginAndEndWith:dateNow];
}
//获取上个月时间
- (void)getLastMonth {
    NSDate *currentDate = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"yyyy-MM"];
    NSCalendar *calendar = [[NSCalendar alloc]initWithCalendarIdentifier: NSGregorianCalendar];
    NSDateComponents *lastMonthComps = [[NSDateComponents alloc]init];
    [lastMonthComps setMonth:-1];
    NSDate *lastMonthDate = [calendar dateByAddingComponents:lastMonthComps toDate:currentDate options:0];
    NSString *lastDateStr = [formatter stringFromDate:lastMonthDate];
    NSLog(@"%@",lastDateStr);
    [self getMonthBeginAndEndWith:lastMonthDate];
}
- (void)getMonthBeginAndEndWith:(NSDate *)newDate {
   if (newDate == nil) {
       newDate = [NSDate date];
   }
   double interval = 0;
   NSDate *beginDate = nil;
   NSDate *endDate = nil;
   
   NSCalendar *calendar = [NSCalendar currentCalendar];
   [calendar setFirstWeekday:2];//设定周一为周首日
   BOOL ok = [calendar rangeOfUnit:NSMonthCalendarUnit startDate:&beginDate interval:&interval forDate:newDate];//某天:NSDayCalendarUnit 周:NSWeekCalendarUnit 月:NSMonthCalendarUnit 年:NSYearCalendarUnit
   if (ok) {
       endDate = [beginDate dateByAddingTimeInterval:interval-1];
   } else {
       return;
   }
   NSDateFormatter *myDateFormatter = [[NSDateFormatter alloc] init];
   [myDateFormatter setDateFormat:@"yyyyMMdd"];
   NSString *beginString = [myDateFormatter stringFromDate:beginDate];
   NSString *endString = [myDateFormatter stringFromDate:endDate];
   NSString *s = [NSString stringWithFormat:@"%@-%@",beginString,endString];
   NSLog(@"%@",s);
}
- (void)getYearBeginAndEndWith:(NSDate *)newDate {
   if (newDate == nil) {
       newDate = [NSDate date];
   }
   double interval = 0;
   NSDate *beginDate = nil;
   NSDate *endDate = nil;
   
   NSCalendar *calendar = [NSCalendar currentCalendar];
   [calendar setFirstWeekday:2];//设定周一为周首日
   BOOL ok = [calendar rangeOfUnit:NSYearCalendarUnit startDate:&beginDate interval:&interval forDate:newDate];//某天:NSDayCalendarUnit 周:NSWeekCalendarUnit 月:NSMonthCalendarUnit 年:NSYearCalendarUnit
   if (ok) {
       endDate = [beginDate dateByAddingTimeInterval:interval-1];
   } else {
       return;
   }
   NSDateFormatter *myDateFormatter = [[NSDateFormatter alloc] init];
   [myDateFormatter setDateFormat:@"yyyyMMdd"];
   NSString *beginString = [myDateFormatter stringFromDate:beginDate];
   NSString *endString = [myDateFormatter stringFromDate:endDate];
   NSString *s = [NSString stringWithFormat:@"%@-%@",beginString,endString];
   NSLog(@"%@",s);
}

2.从时间字符串中获取“年-月-日-时-分-秒”

1.后台返回的数据为:detailModel.trans_time = @"20220329172713";
2.根据上面返回的时间转为:self.timeLB.text = @"2022年03月29日 17:27:13";
3.下面comp1的各个元素小于10的情况需要补个0,因为这边自动省略0,比如9日,自动为9日,但是显示的时候最好为09日

//数据处理赋值
- (void)setDetailModel:(BBXProfitDetailModel *)detailModel {
    _detailModel = detailModel;
    NSCalendar *gregorian = [[NSCalendar alloc]
     initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    unsigned unitFlags = NSCalendarUnitYear |
     NSCalendarUnitMonth |  NSCalendarUnitDay |
     NSCalendarUnitHour |  NSCalendarUnitMinute |
     NSCalendarUnitSecond | NSCalendarUnitWeekday;
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyyMMddHHmmss"];
    [formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Asia/Shanghai"]];
    NSDate *dateOne = [formatter dateFromString:detailModel.trans_time];//后台返回的数据为:detailModel.trans_time = @"20220329172713";
    NSDateComponents *comp1 = [gregorian components: unitFlags
     fromDate:dateOne];
    NSString *monthStr = @"";
    NSString *dayStr = @"";
    NSString *hourStr = @"";
    NSString *minuteStr = @"";
    NSString *secondStr = @"";
    if (comp1.month>=0 && comp1.month<10) {
        monthStr = [NSString stringWithFormat:@"0%ld",(long)comp1.month];
    } else {
        monthStr = [NSString stringWithFormat:@"%ld",(long)comp1.month];
    }
    if (comp1.day>=0 && comp1.day<10) {
        dayStr = [NSString stringWithFormat:@"0%ld",(long)comp1.day];
    } else {
        dayStr = [NSString stringWithFormat:@"%ld",(long)comp1.day];
    }
    if (comp1.hour>=0 && comp1.hour<10) {
        hourStr = [NSString stringWithFormat:@"0%ld",(long)comp1.hour];
    } else {
        hourStr = [NSString stringWithFormat:@"%ld",(long)comp1.hour];
    }
    if (comp1.minute>=0 && comp1.minute<10) {
        minuteStr = [NSString stringWithFormat:@"0%ld",(long)comp1.minute];
    } else {
        minuteStr = [NSString stringWithFormat:@"%ld",(long)comp1.minute];
    }
    if (comp1.second>=0 && comp1.second<10) {
        secondStr = [NSString stringWithFormat:@"0%ld",(long)comp1.second];
    } else {
        secondStr = [NSString stringWithFormat:@"%ld",(long)comp1.second];
    }
    self.timeLB.text = [NSString stringWithFormat:@"%ld年%@月%@日 %@:%@:%@",(long)comp1.year,monthStr,dayStr,hourStr,minuteStr,secondStr];//根据上面返回时间结果为:self.timeLB.text = @"2022年03月29日 17:27:13";
}

从时间字符串中提取出:时/分/秒

@property (nonatomic, copy) NSString *orderTime; //有秒

//定时器回调
- (void)timerAction {

    if (self.isStopTime) {
        [self stopTimer];
        return;
    }
    _countdownInterval -= 1;
    //_label.text = [NSString stringWithFormat:@"%li",(long)_countdownInterval];
    NSDateFormatter *date=[[NSDateFormatter alloc] init];
    [date setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSDate *d = [date dateFromString:self.orderItem.orderTime];
    NSTimeInterval late=[d timeIntervalSince1970]*1;
    NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
    NSTimeInterval now=[dat timeIntervalSince1970]*1;
    NSTimeInterval cha=now-late;
    secondsCountDown = 180 - cha;
//    secondsCountDown -= 1;//倒计时-1
    NSString *str_hour = [NSString stringWithFormat:@"%02ld",secondsCountDown/3600];//重新计算,时/分/秒
    NSString *str_minute = [NSString stringWithFormat:@"%02ld",(secondsCountDown%3600)/60];
    NSString *str_second = [NSString stringWithFormat:@"%02ld",secondsCountDown%60];
    NSString *format_time = [NSString stringWithFormat:@"%@分%@秒",str_minute,str_second];
    self.countdownTimeLb.text = [NSString stringWithFormat:@"座位已成功锁定,请在%@完成支付",format_time];
    ......
}

3.获取当前控制器类扩展

获取当前控制器类扩展,相关链接:https://pan.baidu.com/s/1J_4bZMXrPjTgw3Uo_2eLPA 提取码: ocvn

4.xib写的的控件通过更新约束来更新布局

https://www.jianshu.com/p/d5b9eab198b8

label的xib宽度约束 label的xib宽度约束根据字符串内容调整

5.UITableViewStyleGrouped样式的tableview顶部有距离

相关链接:https://blog.csdn.net/LIUXIAOXIAOBO/article/details/116304219
https://www.jianshu.com/p/9bab692ffab7
https://www.jianshu.com/p/3587474a12da

顶部有距离 解决方法

6.tableView的空数据占位图可以用_tableView.backgroundView

创建先设置空 设置占位图

7.iOS MVVM的理解与分析

https://www.jianshu.com/p/6560505fa0f1

8.百度地图定位权限没有添加完整导致无法定位

旧的百度地图开发定位的权限只需要一种,现在最新的定位需要三种权限。

百度地图定位需要的权限 百度地图新旧SDK

9.runtime的应用(百度地图弹框的模态跳转方式设置)

场景:bbx公务通司机端app已派单页面点击订单上面的导航按钮会先弹框百度的免责申明页面,因为这个项目比较早开发,现在在系统13以上的苹果机上运行会出现问题,13系统模态弹框的方式改变了而这里的跳转还保留原先的跳转,导致页面模态出来的时候充不满屏幕,底部的拒绝和接受按钮被挡住了,所以无法操作进入到地图页面会一直停留在这个页面。

解决:这个时候一个可以更新百度地图的sdk但比较麻烦,通过控制器的属性modalPresentationStyle更改也没有效果(原因可能是改了以后又被调用的百度里面方法给覆盖或者就是无法正确获取当前这个免责申明的控制器),所以可以通过runtime写一个控制器的分类进行系统的模态方法交换,在自己的方法里面更改模态的属性即可成功,也不需要额外去调用操作这个分类,百度地图跳转弹框的时候自己底层会触发这个方法进行交换。

相关链接:https://www.cnblogs.com/ZhangShengjie/p/9131414.html

相关图片:

已派单页面 免责申明页面

分类代码:

控制器的分类.h

//
//  UIViewController+BBX.h
//  DriverOfficer
//
//  Created by Kevin on 2022/5/10.
//  Copyright © 2022 bbxpc.com. All rights reserved.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIViewController (BBX)

@end

NS_ASSUME_NONNULL_END

控制器的分类.m

//
//  UIViewController+BBX.m
//  DriverOfficer
//
//  Created by Kevin on 2022/5/10.
//  Copyright © 2022 bbxpc.com. All rights reserved.
//

#import "UIViewController+BBX.h"
#import <objc/message.h>

@implementation UIViewController (BBX)

+ (void)load {
    //交换系统方法
    swizzleMethod([self class], @selector(presentViewController:animated:completion:), @selector(bbx_presentViewController:animated:complete:));
}

void swizzleMethod(Class cls, SEL originalSelector, SEL swizzledSelector)
{
    Method originalMethod = class_getInstanceMethod(cls, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
    
    BOOL didAddMethod =
    class_addMethod(cls,
                    originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));
    
    if (didAddMethod) {
        class_replaceMethod(cls,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

- (void)bbx_presentViewController:(UIViewController *)vc animated:(BOOL)animated complete:(void (^ __nullable)(void))completion {
    vc.modalPresentationStyle = UIModalPresentationFullScreen;//设置复合13以上系统的模态方式
    [self bbx_presentViewController:vc animated:animated complete:completion];
}

@end

10.break与return的使用

11.const、extern、static用法

https://www.jianshu.com/p/0321e121214e
https://blog.csdn.net/winzlee/article/details/50790571

const static static static extern1.png extern2.png extern与const结合

12.贝泽尔曲线画圆角

@property (weak, nonatomic) IBOutlet UILabel *remarkLabel2;

[_remarkLabel2 zx_roundingCorner:UIRectCornerTopRight|UIRectCornerBottomRight|UIRectCornerTopLeft|UIRectCornerBottomLeft withRadius:5];

- (void)zx_roundingCorner:(UIRectCorner)corner withRadius:(CGFloat)radius {
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corner cornerRadii:CGSizeMake(radius, radius)];
    CAShapeLayer *layer = [[CAShapeLayer alloc] init];
    layer.path = path.CGPath;
    self.layer.mask = layer;
}

13.iOS自动测试简介

iOS自动化测试的那些干货:https://www.jianshu.com/p/b5cbe2409672
ios自动化测试(xcode自带的UI测试):https://www.jianshu.com/p/877f2a1dcabc
Xcode 自带单元测试 :https://juejin.cn/post/6844903628809961479

14.iOS高仿微信发朋友圈,图片拖拽,删除组件

https://blog.csdn.net/JianglongHuang/article/details/82431732

15.UITextView的输入字符字数等限定

https://www.cnblogs.com/linxiu-0925/p/5411356.html

16.

17.数组排序大总结

字典数组按key分组和排序:https://blog.csdn.net/pre_eminent/article/details/40475287
对数组内元素进行排序:https://lequ7.com/guan-yu-iosios-dui-shu-zu-nei-yuan-su-jin-xing-pai-xu.html
数组按照某一属性快速排序:https://www.jianshu.com/p/04a3809845ac

1.根据数组内部某个属性字段进行排序

以BBX司机端地图司机分布为例,地图上非空闲展示在空闲上面

//网络请求数据,排序核心代码:
if (status == 200) {//成功
   [self.orderArray removeAllObjects];//移除所有数据
    [self.mapView removeAnnotations:self.mapView.annotations];//移除地图上的所有标注
    NSArray *dataA = [resultObj.data[@"result"] copy];
    self.orderArray = [BBXRepDriveDistributeModel mj_objectArrayWithKeyValuesArray:dataA];
    
    //重新排序
    NSMutableArray *kongArr = [[NSMutableArray alloc] init];//空闲
    NSMutableArray *noKongArr = [[NSMutableArray alloc] init];//非空闲
    for (BBXRepDriveDistributeModel *disModel in self.orderArray) {
        if (kStrEqual(disModel.show_status, @"0")) {//0:空闲
            [kongArr addObject:disModel];
        } else {
            [noKongArr addObject:disModel];
        }
    }
    NSArray *kong = [NSArray arrayWithArray:kongArr];//空闲
    NSArray *noKong = [NSArray arrayWithArray:noKongArr];//非空闲
    noKong = [noKong arrayByAddingObjectsFromArray:kong];//kong排在noKong后面,后加入描点在最上面
    self.orderArray = [NSMutableArray arrayWithArray:noKong];
}
.h文件
排序管理类.m文件

#import "BBXDiaoduSortArrayManager.h"

@implementation BBXDiaoduSortArrayManager

+ (instancetype)shareManager {
    static BBXDiaoduSortArrayManager * manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[super allocWithZone:NULL] init];//[[BBXDiaoduSortArrayManager alloc] init];
        manager.model = [[OrderListModel alloc]init];
        manager.pickArray = [[NSMutableArray alloc]init];
        manager.sendArray = [[NSMutableArray alloc]init];
        manager.chukouPArray = [[NSMutableArray alloc]init];
        manager.rukouSArray = [[NSMutableArray alloc]init];
    });
    return manager;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    return [self shareManager];
}

+ (id)copyWithZone:(struct _NSZone *)zone {
    return [self shareManager];
}

- (id)copy {
    return self;
}

- (void)setModel:(OrderListModel *)model {
    _model = model;
}

//订单数组进行排序获取新的订单数组
- (NSMutableArray *)getSortOrderListWithArray:(NSMutableArray *)array {
    
    NSMutableArray *orderArray = [[NSMutableArray alloc]init];
    
    //代驾模式
    BOOL isBaoBang = NO;
    if ([BBXDriverInfo shareManager].isSupportDesignatedModel == DriverSceneIsSupportDesignatedModelSupport &&
        [BBXDriverInfo shareManager].driverServiceSceneMode == DriverServiceSceneModeInDesignatedModel) {
        if ([BBXDriverInfo shareManager].designatedDriverServiceState == DesignatedDriverServiceStateOffRunning) { //未报班
            isBaoBang = NO;
        } else {
            isBaoBang = YES;
        }
    } else {//非代驾模式
        if ([BBXDriverInfo shareManager].driverStatus == YH_Driver_Status_No_BaoBang) { //未报班
            isBaoBang = NO;
        } else {
            isBaoBang = YES;
        }
    }
    
    //1.获取当前班次的调度id
    NSString *dispatchId = @"";
    if (!isBaoBang) { //未报班
        dispatchId = @"";
    } else {
        dispatchId = [BBXDriverInfo shareManager].cur_pre_dispatched_id;
    }
    
    //2.获取各部分订单(过滤出预派单和非预派单;预派单包含当前调度和其他调度id的订单;非预派单里面包含有序和无序;有序里面包含接客有序和送客有序)
    NSMutableArray *currentPreSentOrderArr = [[NSMutableArray alloc] init];//装载预派单(当前调度id的单)
    NSMutableArray *unCurrentPreSentOrderArr = [[NSMutableArray alloc] init];//装载预派单(非当前调度id的单)
    NSMutableArray *normalOrderArr = [[NSMutableArray alloc] init];//装载正常单
    NSMutableArray *wuXuArray = [[NSMutableArray alloc]init];//无序
    NSMutableArray *youXuArray = [[NSMutableArray alloc]init];//有序
    NSMutableArray *youPickArray = [[NSMutableArray alloc]init];//有序接客
    NSMutableArray *youSendArray = [[NSMutableArray alloc]init];//有序送客
    NSMutableArray *chukouPArray = [[NSMutableArray alloc]init];//出口
    NSMutableArray *rukouSArray = [[NSMutableArray alloc]init];//入口
    //获取预派与正常订单
    for (OrderListModel *model in array) {
        if ([model.flights_no isEqualToString:@"prestandbycitys"]) {//预派单
            if ([model.dispatch_id isEqualToString:dispatchId]) {//当前班次
                [currentPreSentOrderArr addObject:model];
            } else {
                [unCurrentPreSentOrderArr addObject:model];
            }
        } else {
            [normalOrderArr addObject:model];
        }
    }
    //获取无序和有序
    for (OrderListModel *model1 in normalOrderArr) {
        if (model1.on_seq == 0 || model1.off_seq == 0) {
            [wuXuArray addObject:model1];
        } else {
            [youXuArray addObject:model1];
        }
    }
    //有序接客和有序送客
    for (OrderListModel *model2 in youXuArray) {
        if (model2.order_status == Order_state_get_on) {
            [youSendArray addObject:model2];//送客
        } else {
            [youPickArray addObject:model2];//接客(注意中间状态?等待乘客确认上车)
        }
    }
    //获取出口
    for (OrderListModel *p1 in normalOrderArr) {
        if (p1.A_entry.count>0) {
            [chukouPArray addObject:p1];
        }
    }
    //获取入口
    for (OrderListModel *s1 in normalOrderArr) {
        if (s1.B_entry.count>0) {
            [rukouSArray addObject:s1];
        }
    }
    
    //3.各部分进行排序(最外层:正常单>本调度id预派>非本调度id预派;正常单里面:有序>无序;有序里面:接客内部有序排列>送客内部有序排列;无序里面:接客>送客;所有内部根据状态排序时相同状态再按时间顺序排序)
    //按订单状态码的大小排序,小的排前面,订单状态相同的再按时间先后排序,时间早的排前面(如:2020-05-09 20:50:32 排在 2020-05-11 10:15:00 之前)
    NSSortDescriptor *sort1 = [NSSortDescriptor sortDescriptorWithKey:@"order_status" ascending:YES];
    NSSortDescriptor *sort2 = [NSSortDescriptor sortDescriptorWithKey:@"appoint_time" ascending:YES];
    
    NSMutableArray *pickArr = [youPickArray sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {//有序接客内部排序
        OrderListModel *m1 = obj1;
        OrderListModel *m2 = obj2;
        if (m1.on_seq<m2.on_seq) {
            return NSOrderedAscending;//升序
        } else {
            return NSOrderedDescending;//降序
        }
    }];
    
    NSMutableArray *sendArr = [youSendArray sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {//有序送客内部排序
        OrderListModel *m1 = obj1;
        OrderListModel *m2 = obj2;
        if (m1.off_seq<m2.off_seq) {
            return NSOrderedAscending;//升序
        } else {
            return NSOrderedDescending;//降序
        }
    }];
    [wuXuArray sortUsingDescriptors:@[sort1,sort2]];//无序内部排序
    [currentPreSentOrderArr sortUsingDescriptors:@[sort1,sort2]];//本调度id预派排序
    [unCurrentPreSentOrderArr sortUsingDescriptors:@[sort1,sort2]];//非本调度id预派排序
    
    //组装数组orderArray
    //正常单排前面,接着是当前调度Id的预派单,接着是非当前调度Id的预派单(先添加排前面)
    [orderArray removeAllObjects];
    [orderArray addObjectsFromArray:pickArr];
    [orderArray addObjectsFromArray:sendArr];
    [orderArray addObjectsFromArray:wuXuArray];
    [orderArray addObjectsFromArray:currentPreSentOrderArr];
    [orderArray addObjectsFromArray:unCurrentPreSentOrderArr];
    for (OrderListModel *models in orderArray) {
        if (!isNullArray(models.locations.passenger)) {
            models.isShowPassTip = YES;
            break;
        }
    }
    
//[orderArray setValue:pickArr forKey:@"pickArr"];//这种写法不对,数组没有这个key-value;如果需要再返回单独数组,
//可以用下面这个方式写一个数组来赋值;或者这边不返回数组,返回一个字典,再把想返回的各个数//组放在字典里面,外面调用的地方直接取字典里
//面的key来取对应的数组
//[orderArray setValue:sendArr forKey:@"sendArr"];
    self.pickArray = pickArr;
    self.sendArray = sendArr;
    self.chukouPArray = chukouPArray;
    self.rukouSArray = rukouSArray;
    return orderArray;
}

@end

18.数组遍历大总结

1.for;这个方法最普通效率一般,一般用于针对下标的处理和反向遍历
2.for in;快速遍历,效率最高
3.enumerateObjectsUsingBlock;block里面的参数包括object,下标以及是否停止遍历,应该说这个能满足基本所有的遍历需求。有下标和运行的对象,还有是否继续遍历的标志。不过反向遍历呢?苹果提供了另外一个方法:enumerateObjectsWithOptions:NSEnumerationReverse usingBlock;效率不咋样

常见遍历方法比较:http://t.zoukankan.com/tangyuanby2-p-7150103.html
遍历性能比较:https://blog.csdn.net/songzhuo1991/article/details/116012426

1.for循环

- (void)setModel:(OrderListModel *)model {
    _model = model;
    if (model.order_status == Order_state_sended) {//接客
        if (model.on_seq == 0 || !model.on_seq) {
            self.pinBgView.image = kImage(@"bbxMapPeople");
        } else {
            
            for (int i = 0; i<self.pickArray.count; i++) {
                if (model.order_id == [self.pickArray[i] order_id]) {//唯一id标识符,当前订单
                    self.numLb.text = [NSString stringWithFormat:@"%d",i+1];
                    self.pinBgView.image = kImage(@"bbxMapPoint");
                    break;//跳出循环
                }
            }
        }
    } else {
        self.numLb.text = @"";
        if (self.isPickMapChuKou == YES) {//接客
            self.pinBgView.image = kImage(@"bbxMapExit");//出口
        } else {
            self.pinBgView.image = kImage(@"bbxMapEnter");//入口
        }
    }
}

2.for in循环

NSMutableArray *temArray = [NSMutableArray array];
for (OrderListModel *model in self.orderArray) {
    if (model.order_status == Order_state_sended && model.order_status != Order_state_get_on && !(model.order_origin.intValue == 999)) {
        [temArray addObject:model];
    }
}
self.clusterManager.dataArray = temArray;//聚合

3.enumerateObjectsUsingBlock

__block NSMutableArray * list_jijia = [[NSMutableArray alloc] init];
__block NSMutableArray * list_normal = [[NSMutableArray alloc] init];

[self.orderArray enumerateObjectsUsingBlock:^(OrderListModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    if(obj.calc_type != 0) {
        [list_jijia addObject:obj];
    } else {
        [list_normal addObject:obj];
    }
}];
enumerateObjectsUsingBlock:遍历多维数组

19.bbx司机端模拟用户下单

大概的需求:模拟用户下单,先获取下单任务列表数组;如果有任务的话对任务进行遍历,每个任务进行执行下单任务并确认任务完成,当全部任务执行完成之后会根据后台返回间隔时间进行重新下单任务,循环运行起来。如果返回任务列表失败则根据间隔时间进行重新下单任务循环。

1.模型类

.h文件 .m文件

2.控制器中代码

2.1属性
@property (nonatomic, strong) BBXTask *simulateOrderModel;// 模拟用户下单-只用公司测试-网约车司机
@property (nonatomic, strong) NSArray *simulateOrderArray;//任务数组

- (BBXTask *)simulateOrderModel {
    if (!_simulateOrderModel) {
        _simulateOrderModel = [[BBXTask alloc]init];
    }
    return _simulateOrderModel;
}

- (NSArray *)simulateOrderArray {
    if (!_simulateOrderArray) {
        _simulateOrderArray = [NSArray array];
    }
    return _simulateOrderArray;
}

2.2方法
- (void)viewDidLoad {
    [super viewDidLoad];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self loadSimulateUsersOrder];//模拟下单-公司测试
    });
}

//1.模拟用户下单-只用于公司测试(只做网约车司机),获取任务列表
- (void)loadSimulateUsersOrder {
    
    NSDictionary *params = @{@"driver_id":@"all",
                             @"line_id":@"all"
                            };
    [BBXAPIHTTP wzx_requestBBXWithParameter:params adnFinishBlock:^(RequestResultObj *resultObj) {
        
        WeakSelf
        if([resultObj.data isKindOfClass:[NSDictionary class]]) {
            
            NSDictionary *infoDic = resultObj.data;
            NSDictionary *result = infoDic[@"result"];
            NSString *sleepOne = result[@"sleep"];
            NSInteger status = [resultObj.data[@"status"] integerValue];

            if(status == 0 && [infoDic isKindOfClass:[NSDictionary class]]) {//成功
                
                self.simulateOrderArray = [NSArray modelArrayWithClass:[BBXTask class] json:result[@"task"]];
                NSInteger sleep = [sleepOne intValue];
                [self takeUpSimulateUsersOrder:self.simulateOrderArray sleep:sleep];//遍历
            } else {//失败没有任务
                
                NSString *dicJsonStr = resultObj.jsonStr;
                NSDictionary *dataDict = [NSDictionary dictionaryWithJsonString:dicJsonStr];
                NSDictionary *extra = dataDict[@"extra"];
                
                if([extra isKindOfClass:[NSDictionary class]]) {
                   
                    NSString *sleepTwo = extra[@"sleep"];
                    NSInteger sleep = [sleepTwo intValue];
                    
                    if (sleep > 0) {
                        
                        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(sleep * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                            
                            [weakSelf loadSimulateUsersOrder];//间隔重新获取下单列表
                        });
                    }
                }
            }
        } else {
           
        }
    } andRequestURl:[BBXURL getSimulateUsersOrder] toCrypt:NO];
}
//接口:模拟用户下单-获取任务列表
+ (NSString *)getSimulateUsersOrder {
    return [self domainInsideTestString:@"/pub/task/test"];
}

//2.遍历任务列表数组
- (void)takeUpSimulateUsersOrder:(NSArray *)simulateOrderArray sleep:(NSInteger)sleep {
    
    int loopCount = 0;
    for (int i=0; i<simulateOrderArray.count; i++) {
        
        self.simulateOrderModel = simulateOrderArray[i];
        [self takeSimulateUsersOrder:self.simulateOrderModel];//下单任务
        loopCount += 1;
    }
    
    if (loopCount==simulateOrderArray.count) {
        
        if (sleep>0) {
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(sleep * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self loadSimulateUsersOrder];//间隔重新获取下单列表
            });
        }
    }
}

//3.模拟用户下单-执行下单任务
- (void)takeSimulateUsersOrder:(BBXTask *)model {
    
    NSDictionary *params = @{@"driver_phone":model.driver_phone?model.driver_phone:@"",
                             @"driver_name":model.driver_name?model.driver_name:@"",
                             @"car_NO":model.car_NO?model.car_NO:@"",
                             @"passenger_id":model.passenger_id?model.passenger_id:@"",
                             @"phone":model.phone?model.phone:@"",
                             @"order_id":model.order_id?model.order_id:@"",
                             @"channel_id":model.channel_id?model.channel_id:@"",
                             @"line_id":model.line_id?model.line_id:@"",
                             @"driver_id":model.driver_id?model.driver_id:@""
                            };
    [BBXAPIHTTP wzx_requestBBXWithParameter:params adnFinishBlock:^(RequestResultObj *resultObj) {
        
        if([resultObj.data isKindOfClass:[NSDictionary class]]) {
            
            NSDictionary *infoDic = resultObj.data;
            NSInteger status = [resultObj.data[@"status"] integerValue];
            NSString *message = infoDic[@"message"];
            
            if(status == 0 && [infoDic isKindOfClass:[NSDictionary class]]) {
                
            } else {
                NSLog(@"%@",message);
            }
        } else {
            
        }
        [self sureSimulateUsersOrder:model];//确认服务
    } andRequestURl:[BBXURL takeSimulateUsersOrder] toCrypt:NO];
}
//接口:模拟用户下单-下单任务
+ (NSString *)takeSimulateUsersOrder {
    return [self domainInsideTestString:@"/api/driver_share/passenger_order_submit"];
}

//4.模拟用户下单-完成任务
- (void)sureSimulateUsersOrder:(BBXTask *)model {
    
    NSDictionary *params = @{@"driver_phone":model.driver_phone,
                             @"driver_name":model.driver_name,
                             @"car_NO":model.car_NO,
                             @"passenger_id":model.passenger_id,
                             @"phone":model.phone,
                             @"order_id":model.order_id,
                             @"channel_id":model.channel_id,
                             @"line_id":model.line_id,
                             @"driver_id":model.driver_id
                            };
    [BBXAPIHTTP wzx_requestBBXWithParameter:params adnFinishBlock:^(RequestResultObj *resultObj) {
        
        if([resultObj.data isKindOfClass:[NSDictionary class]]) {
            
            NSDictionary *infoDic = resultObj.data;
            NSInteger status = [resultObj.data[@"status"] integerValue];
            if(status == 0 && [infoDic isKindOfClass:[NSDictionary class]]) {
                
            } else {
                
            }
        } else {
            
        }
    } andRequestURl:[BBXURL sureSimulateUsersOrder] toCrypt:NO];
}
//接口:模拟用户下单-确认服务
+ (NSString *)sureSimulateUsersOrder {
    return [self domainInsideTestString:@"/api/driver_share/serve_self"];
}

19.bbx漳州交警语音播报需求逻辑

20.接客地图导航中按顺序接客连续滑动操作

需求:在接客地图展示的订单会按照约定的接客顺序进行路线规划,以司机当前位置为起点,出城口为终点,几个订单当做途经点进行串联画折线。点击开始导航按钮进入导航,默认导航到第一个订单的起点位置,在导航页面滑动接到乘客请求接口,请求接口成功之后会继续停留在导航页面继续导航到第二个订单的起点位置,以此类推直到最后一个订单接到成功后退出地图。每次导航的起点都是司机当前位置,终点是要导航订单的起点位置。

接客地图页面 接客地图导航页面

核心代码:

//开始导航按钮回调(智能调度)
- (void)diaoduStartNavigation:(NSMutableArray*)dataArray {
    NSMutableArray *temArray = [NSMutableArray array];
    for (OrderListModel *model in dataArray) {
        if (model.order_status == Order_state_sended && model.order_status != Order_state_get_on && !(model.order_origin.intValue == 999)) {//接客地图订单,未上车
            [temArray addObject:model];
        }
    }
    if (temArray.count>0) {
        [BBXMapNaviManager shareManager].diaoduOrderArray = temArray;
        [[BBXMapNaviManager shareManager] diaoduBeginMapNaviWithOrderArray:temArray];//开始导航回调
        [BBXMapNaviManager shareManager].isOrderListJump = NO;
        [BBXMapNaviManager shareManager].isDiaoduPickMapJump = YES;
        [BBXMapNaviManager shareManager].carTakeUPBlock = ^{//导航里面接到乘客按钮回调
            OrderListModel *firstModel = [self getNeedModel];//获取到要接的乘客
            [self diaoduPassengerGetOnWithOrderModel:firstModel];
        };
        [BBXMapNaviManager shareManager].updatePhoneCallback = ^{//打电话回调
            OrderListModel *firstModel = [self getNeedModel];
            [self.mapPopupView setPhoneCountWith:firstModel];
        };
    }
}
//1.开始导航(智能调度)
- (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 == Order_state_sended) {//接客

        dest_lat = orderListModel.start_lat;
        dest_lng = orderListModel.start_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];
}

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

3.//根据起点和终点坐标进行规划路线
- (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;
    }
}
//1.滑动接到乘客请求(智能调度)
- (void)diaoduPassengerGetOnWithOrderModel:(OrderListModel *)diaoduModel {
    @weakify(self);
    //司机对指定订单执行上车操作(司机接到乘客后,在订单列表中滑动“接到乘客”操作)
    [SVProgressHUD show];
    [[NetworkClient sharedInstance] passengerGetOnWithOrderModel:diaoduModel completeBlock:^(NSDictionary *responseDictionary) {
        [SVProgressHUD dismiss];
        @strongify(self);
        NSInteger status = [responseDictionary[@"status"] integerValue];
        if (status == 0 && responseDictionary != nil) {//成功
            dispatch_async(dispatch_get_main_queue(), ^{
                
                [self diaoDuSortOrderArray:self.orderArray];//wzx
                [self getIsUseModelInArray:diaoduModel];//更新上车状态
                OrderListModel *nextModel = [self getNeedModel];
                if (nextModel.order_id.length > 0) {
                    OrderViewModel *orderViewModel = [[OrderViewModel alloc] initWithOrderModel:nextModel];//这里的model有可能是默认的,需要判断model是否可用
                    [[BBXMapNaviManager shareManager]updateMapNaviWithOrderViewModel:orderViewModel];
                    NSLog(@"更新视图");
                } else {
                    NSLog(@"接客结束");
                    [[BBXMapNaviManager shareManager]exitMap];
                }
                [self refreshEvent:NO];//刷新地图
            });
        } else {//失败
            NSString *message = responseDictionary[@"message"];
            dispatch_async(dispatch_get_main_queue(), ^{
                [SKToast showWithText:message];
            });
        }
    }];
}

//2.获取每次需要接的乘客(排在第一个)
- (OrderListModel*)getNeedModel {
    NSMutableArray *dataArry = [NSMutableArray array];
    for (OrderListModel *model in self.orderArray) {
        if (model.order_status == Order_state_sended && model.order_status != Order_state_get_on && !(model.order_origin.intValue == 999)) {//接客地图订单,未上车
            [dataArry addObject:model];
        }
    }
    
    NSMutableArray *tempArray = [NSMutableArray array];
    if (dataArry.count>0) {
        for (OrderListModel * model in dataArry) {
            if (!model.isGetUpCarSuccess) {
                [tempArray addObject:model];
            }
        }
    }
    //这里如果获取不到乘客了,传的是默认的model,在更新的时候需要判断这个model是否可用
    OrderListModel *tempModel = [[OrderListModel alloc]init];
    if (tempArray.count > 0) {
        tempModel = tempArray.firstObject;
    }
    return tempModel;
}

//3.接客成功后将接客状态置为成功
- (void)getIsUseModelInArray:(OrderListModel*)model {
    NSMutableArray *dataArry = [NSMutableArray array];
    for (OrderListModel *listModel in self.orderArray) {
        if (listModel.order_status == Order_state_sended && listModel.order_status != Order_state_get_on && !(listModel.order_origin.intValue == 999)) {//接客地图订单,未上车
            [dataArry addObject:listModel];
        }
    }
    
    for (OrderListModel *cmodel in dataArry) {
        if (model.order_id == cmodel.order_id) {//乘客的唯一标识
            cmodel.isGetUpCarSuccess = true;
            return;
        }
    }
}

//4.智能调度订单数组进行排序
- (void)diaoDuSortOrderArray:(NSMutableArray *)orderArr {
   //进行排序获取新的排好的数组
    self.orderArray = [[BBXDiaoduSortArrayManager shareManager]getSortOrderListWithArray:orderArr];
}

备注:Lin

//假设JMUserInfoModel是我们的model,userArray就是网络请求回来之后存放数据的数组
JMUserInfoModel模型内部:
@interface JMUserInfoModel : NSObject
@property(nonatomic, copy) NSString *idCode;//乘客的唯一标识
@property(nonatomic, assign) BOOL isUse;//标记这个乘客是否已经使用
@end

@property(nonatomic, strong) NSArray<JMUserInfoModel*> *userArray;

//第一次网络请求设置
- (void)getUserData {
    //通过网络请求给userArray赋值
}

//第一次加载的UI
- (void)setUserUI {
    //1.获得需要展示的model
    JMUserInfoModel * model = [self getNeedModel];
    //2.更新视图
}

1.//假设滑动接客网络请求
- (void)getNetWork {
    //1.获取到要请求的乘客model
    JMUserInfoModel * model = [self getNeedModel];
    //2.网络请求
    
    //3.在网络请求成功里面去将已经送达的乘客isUse设置为true
    [self getIsUseModelInArray:model];
    
    //4.获得需要展示的model(注意,这里的model有可能是默认的,需要判断model是否可用)
    JMUserInfoModel * nextModel = [self getNeedModel];
    
    //如果可用更新视图
    if (nextModel.idCode.length > 0)  {
        //5.更新视图
    } else {
        //如果不可以用,证明后面没有乘客。处理结束的需求
    }
}

2.//每次获取使用的model
- (JMUserInfoModel*)getNeedModel {
    NSMutableArray *tempArray = [NSMutableArray array];
    for (JMUserInfoModel * model in self.userArray) {
        if (!model.isUse) {
            [tempArray addObject:model];
        }
    }
    //这里如果获取不到乘客了,传的是默认的model,在更新的时候需要判断这个model是否可用
    JMUserInfoModel *tempModel = [[JMUserInfoModel alloc]init];
    if (tempArray.count > 0) {
        tempModel = tempArray.firstObject;
    }
    return tempModel;
}

3.//通过传入的model改变在userArray的isUse的值
- (void)getIsUseModelInArray:(JMUserInfoModel*)model {
    for (JMUserInfoModel * cmodel in self.userArray) {
        //这里的idCode是指你这个乘客的唯一标识
        if (model.idCode == cmodel.idCode) {
            cmodel.isUse = true;
            return;
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读