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

开发问题笔记(十三)

作者: Kevin_wzx | 来源:发表于2020-09-28 16:02 被阅读0次

目录

1.App内打开第三方地图进行导航

1.App内打开第三方地图进行导航

App内打开第三方地图进行导航;举例以下例子:后台用的百度坐标,返回百度坐标,可以直接打开百度地图。如果要打开高德和腾讯则需要先把坐标转成火星坐标再去调用,不然就会有定位偏差。注意:调用百度的时候下面链接里面的这个方法会有定位偏差错误(@"baidumap://map/direction?origin={{我的位置}}&destination=latlng:%@,%@|name=北京&mode=driving&coord_type=gcj02"),使用这个方法正确不会偏差(@"baidumap://map/direction?origin={{我的位置}}&destination=%f,%f&mode=driving&src=ios.LanHai.%@")

相关链接:
https://www.jianshu.com/p/1768de507727
https://blog.csdn.net/ruglcc/article/details/52023274

常用地图坐标系介绍:

  • WGS-84:是国际标准,GPS坐标(Google Earth使用、或者GPS模块)
  • GCJ-02:中国坐标偏移标准,Google地图、高德、腾讯使用
  • BD-09 :百度坐标偏移标准,Baidu地图使用

下面.m文件坐标转换方法链接:https://juejin.im/post/6844903591090585607

  • 坐标初始化写法(2种)
1. CLLocationCoordinate2D coords = (CLLocationCoordinate2D){0, 0};    //纬度,经度
2. CLLocationCoordinate2D coords = CLLocationCoordinate2DMake(39.915352,116.397105);//纬度,经度

补充:
CLLocation *location = [[CLLocation alloc] initWithLatitude:startLat longitude:startLng];
CLLocationCoordinate2D coordinate = location.coordinate;
CLLocationCoordinate2D startCoor = CLLocationCoordinate2DMake(startLat, startLng);
  • 将CLLocationCoordinate2D类型转换为数字或字符串
CLLocationCoordinate2D centerCoord; 
centerCoord.latitude = self.locModel.userLocation.coordinate.latitude; 
centerCoord.longitude = self.locModel.userLocation.coordinate.longitude; 
NSString * tmpLat = [[NSString alloc] initWithFormat:@"%g",centerCoord.latitude]; 
NSString * tmpLong = [[NSString alloc] initWithFormat:@"%g",centerCoord.longitude]; 
NSLog("用户的纬度为:%@",tmpLat); 
NSLog("用户的经度是:%@",tmpLong); 
  • 将字符串转换成CLLocationCoordinate2D类型
NSString *latitude = @“25.678”;
NSString *longitude = @“116.789”;
CLLocationDegrees dest_lat = [latitude doubleValue];
CLLocationDegrees dest_lng = [longitude doubleValue];
CLLocationCoordinate2D endCoor = CLLocationCoordinate2DMake(dest_lat, dest_lng);
  • 封装打开第三方地图方法的代码
.h  文件
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(NSUInteger, BBXOpenThreeMapManagerType) {

    BBXOpenThreeMapManagerType_Baidu, //百度
    BBXOpenThreeMapManagerType_Gaode, //高德
    BBXOpenThreeMapManagerType_Tenxun, //腾讯
    BBXOpenThreeMapManagerType_Apple, //苹果
};

@interface BBXOpenThreeMapManager : NSObject

@property (nonatomic, assign) BBXOpenThreeMapManagerType openThreeMapType;

// 调用第三方地图导航
+ (void)gotoThreeMapToNavgationWithMapType:(BBXOpenThreeMapManagerType)type Longitude:(NSString *)longitude Latitude:(NSString *)latitude;

@end
.m文件(坐标转换用的第三方:HZLocationConverter)
// 调用第三方地图导航
+ (void)gotoThreeMapToNavgationWithMapType:(BBXOpenThreeMapManagerType)type Longitude:(NSString *)longitude Latitude:(NSString *)latitude {
    
    if (type == BBXOpenThreeMapManagerType_Baidu) {// 百度地图
        
        if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"baidumap://"]]) {
            
            NSString *appName = [NSBundle mainBundle].infoDictionary[@"CFBundleDisplayName"];
            NSString *urlString1 = [[NSString stringWithFormat:@"baidumap://map/direction?origin={{我的位置}}&destination=%f,%f&mode=driving&src=ios.LanHai.%@",[latitude doubleValue],[longitude doubleValue],appName] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];//帮邦行司机端bundle:com.LanHai.bbxDriver
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString1]];
        } else {
            
            [SKToast showWithText:@"您未安装地图APP,无法导航"];
        }
    } else if (type == BBXOpenThreeMapManagerType_Gaode) {// 高德地图-GCJ-02火星坐标(后台传回来的是百度坐标,需要转换)
        
        if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"iosamap://"]]) {
            
            CLLocationDegrees dest_lat = [latitude doubleValue];
            CLLocationDegrees dest_lng = [longitude doubleValue];
            CLLocationCoordinate2D endCoor = CLLocationCoordinate2DMake(dest_lat, dest_lng);
            CLLocationCoordinate2D gaodeLoca = [HZLocationConverter transformFromBaiduToGCJ:endCoor];
            
            NSString *urlString2 = [[NSString stringWithFormat:@"iosamap://navi?sourceApplication=%@&backScheme=%@&lat=%f&lon=%f&dev=0&style=2",@"导航功能",@"nav123456",gaodeLoca.latitude,gaodeLoca.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString2]];
        } else {
            
            [SKToast showWithText:@"您未安装地图APP,无法导航"];
        }
    } else if (type == BBXOpenThreeMapManagerType_Tenxun) {// 腾讯地图-GCJ-02火星坐标
        
        if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"qqmap://"]]) {
            
            CLLocationDegrees dest_lat = [latitude doubleValue];
            CLLocationDegrees dest_lng = [longitude doubleValue];
            CLLocationCoordinate2D endCoor = CLLocationCoordinate2DMake(dest_lat, dest_lng);
            CLLocationCoordinate2D gaodeLoca = [HZLocationConverter transformFromBaiduToGCJ:endCoor];
            
            NSString *urlString3 = [[NSString stringWithFormat:@"qqmap://map/routeplan?from=我的位置&type=drive&tocoord=%f,%f&to=终点&coord_type=1&policy=0",gaodeLoca.latitude,gaodeLoca.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString3]];
        } else {
            
            [SKToast showWithText:@"您未安装地图APP,无法导航"];
        }
    } else if (type == BBXOpenThreeMapManagerType_Apple) {// 苹果地图
        
            CLLocationCoordinate2D loc = CLLocationCoordinate2DMake([latitude doubleValue], [longitude doubleValue]);//终点坐标
            MKMapItem *currentLoc = [MKMapItem mapItemForCurrentLocation];//用户位置
            MKMapItem *toLocation = [[MKMapItem alloc]initWithPlacemark:[[MKPlacemark alloc]initWithCoordinate:loc addressDictionary:nil] ];
            NSArray *items = @[currentLoc,toLocation];//终点位置
            NSDictionary *dic = @{
                                  MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
                                  MKLaunchOptionsMapTypeKey : @(MKMapTypeStandard),
                                  MKLaunchOptionsShowsTrafficKey : @(YES)
                                  };
            [MKMapItem openMapsWithItems:items launchOptions:dic];
    } else {
        
        NSLog(@"没有发现地图");
    }
}

- (void)setOpenThreeMapType:(BBXOpenThreeMapManagerType)openThreeMapType {
    
    self.openThreeMapType = openThreeMapType;
}

2.广告标识符idfa

idfa为苹果跟踪广告的主要标识;在同一个设备上的所有App都会取到相同的值,是苹果专门给各广告提供商用来追踪用户而设的。广告标示符是由系统存储着的,适用于对外例如广告推广,换量等跨应用的用户追踪等。但是这个值不是唯一确定的,也就是说用户可以根据自己的意愿来还原或者禁止获取这个值。用户可以通过苹果手机设置--->隐私--->广告来操作。

链接:
https://www.jianshu.com/p/8e2846dc8a03
https://www.jianshu.com/p/9d059c17481d

实现代码 上架AppStore的时候注意勾选

3.苹果自带大标题导航栏(类似App Store效果)

有的时候需求需要展示苹果的大字效果,如下图。
链接:https://www.jianshu.com/p/f32ce236da67

设置大标题效果 大标题效果
关闭大标题效果:
if (@available(iOS 11.0, *)) {// 去除苹果导航栏新特性(LargeTitle)
    [[UINavigationBar appearance] setPrefersLargeTitles:NO];
    } else {
        
    }

4.封装的cell里面,在模型里设置动态高度返回到VC

根据model计算cell高度

5.对帮邦循环判断2个组同时满足

场景:比如如下列表数据,有2种cell,上面一种是快线订单类型,组头根据下车的站点来返回,即所有人里面有几个不同下车站点就有组,每个组里又包含了一起下车的人(也就是几个人这个站点组里面就有几个cell);下面一种cell是网约车订单,只有一个组,组里有可能有多笔订单。现在需要通过找到快线订单每个组里的每个订单即每个cell里面未付款的数量和已付款的数量,以及网约车订单里是否已经下车了根据这个来判断是否让结束行程按钮状态蓝色可用还是灰色禁用。

数据列表
  • 判断的代码片段
    上面cell的判断
下面cell的判断 是否显示按钮可用的判断
  • 类似判断代码
    BOOL isGetCar = NO;
    BOOL isOutCar = NO;

    __block NSInteger currentGetCarCount = 0;
    __block NSInteger currentOutCarCount = 0;

    [self.sectionArray2 enumerateObjectsUsingBlock:^(LLShareBottomItemModel*  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        //需要判断的状态
        if (obj.isSelected) {
            currentGetCarCount +=1;
        }
    }];
    //证明所有的状态都改了
    if (self.sectionArray2.count == currentGetCarCount) {
        isGetCar = YES;
    }
    
    [self.sectionArray1 enumerateObjectsUsingBlock:^(LLShareBottomItemModel*  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
           //需要判断的状态
        if (obj.isSelected) {
            currentOutCarCount +=1;
        }
    }];
    
    //证明所有的状态都改了
     if (self.sectionArray2.count == currentGetCarCount) {
         isOutCar = YES;
     }
    
    //都满足条件了
    if (isGetCar && isOutCar) {
        
    }
    __block NSInteger currentCount = 0;
    __block NSInteger allModelCount = 0;
    [self.sectionArray2 enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        //首先判断dataArray里面是不是你要得model
        if ([obj isKindOfClass:[LLShareBottomItemModel class]]) {
             //获取有多少个model
            allModelCount += 1;
            LLShareBottomItemModel *model = (LLShareBottomItemModel *)obj;
            //你的判断条件
            if (model.isSelected) {
                currentCount += 1;
            }
        }
    }];
    //说明你的要求达到了
    if (allModelCount == currentCount) {
        
    }

6.因为百度地图SDK只能允许真机器

帮邦行司机端运行模拟器报错如下,因为百度地图的SDK的原因,所以只能运行真机。

7.计算时间差及时间处理相关

通过两个时间点进行计算时间差
相关链接:
NSDate计算时间差:https://blog.csdn.net/prettyfei1123/article/details/75015523
时区8小时问题:https://www.jianshu.com/p/df41659b06a9
时间类型相互转化:https://www.cnblogs.com/sundaysgarden/articles/10484446.html
https://www.jianshu.com/p/dfbaff446a08
粗略计算两个时间天数差值:https://blog.csdn.net/qq_16588415/article/details/52818151
在线计算日期差:https://riqicha.51240.com/?kaishi=2019-02-02-00-00-00&jieshu=2020-10-31-00-00-00

  • 1.将字符串转成NSDate类型
//将字符串转成NSDate类型
- (NSDate *)dateFromString:(NSString *)dateString {
    
    NSDateFormatter *inputFormatter= [[NSDateFormatter alloc] init];
    [inputFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"CN"]];
    [inputFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSDate *inputDate = [inputFormatter dateFromString:dateString];
    //将转换回来的对象手动加上8小时,回到北京时间
    NSDate *localeDate = [inputDate dateByAddingTimeInterval:8 * 60 * 60];
    return localeDate;
}
  • 2.传入今天的时间,返回明天的时间(明天的零点)
//传入今天的时间,返回明天的时间
- (NSString *)getTomorrowDay:(NSDate *)aDate {

    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSDateComponents *components = [gregorian components:NSCalendarUnitWeekday |NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:aDate];
    [components setDay:([components day]+1)];
    NSDate *beginningOfWeek = [gregorian dateFromComponents:components];
    NSDateFormatter *dateday = [[NSDateFormatter alloc] init];
    [dateday setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    return [dateday stringFromDate:beginningOfWeek];
}
  • 通过NSDate计算时间差(结果差值为时间戳)
模型里面的时间字段
@property (nonatomic, strong) NSString *apply_time;

//计算时间间隔
- (void)takeTimeDifference {
    
    NSDateFormatter *format = [[NSDateFormatter alloc]init];
    [format setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    [format setLocale:[NSLocale currentLocale]];
    NSDate *applyDate = [self dateFromString:self.model.apply_time];
    NSString *invoiceTimeStr = [self getTomorrowDay:applyDate];
    NSDate *currentDate = [format dateFromString:invoiceTimeStr];
    NSDate *date = [NSDate date];
    //消除8小时的误差
    NSTimeZone *zone = [NSTimeZone systemTimeZone];
    NSInteger interval = [zone secondsFromGMTForDate:date];
    //追加8小时
    NSDate *localeDate = [date dateByAddingTimeInterval: interval];
    currentDate = [currentDate dateByAddingTimeInterval:interval];
    //计算时间差间隔
    NSTimeInterval timeBetween = [localeDate timeIntervalSinceDate:currentDate];
    self.timeDifferenceDay = timeBetween;
    NSLog(@"间隔天数:%ld天",(long)timeBetween);
    //根据相差的秒数,看是否大于180天
    if (timeBetween > 180*24*3600) {//86400一天长度的时间戳,24*60*60
        
    }
}
  • 备注:其他2个计算时间差方法,精准度未验证
    方法一:
- (void)takeTimeDifference {
    
    NSCalendar *gregorian = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
    [gregorian setFirstWeekday:0];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSDate *fromDate;
    NSDate *toDate;
    NSDate *applyDate = [self dateFromString:self.model.apply_time];
    NSString *invoiceTimeStr = [self getTomorrowDay:applyDate];
    NSDate *localeDate = [NSDate date];
    NSDate *nowDate = [localeDate dateByAddingTimeInterval:8 * 60 * 60];//将转换回来的对象手动加上8小时,回到北京时间(UTC:世界标准时间)
    NSString *invoiceTimeStr2 = [self getTomorrowDay:nowDate];
    [gregorian rangeOfUnit:NSDayCalendarUnit startDate:&fromDate  interval:NULL forDate:[dateFormatter dateFromString:invoiceTimeStr]];
    [gregorian rangeOfUnit:NSDayCalendarUnit startDate:&toDate  interval:NULL forDate:nowDate];
    NSDateComponents *dayComponents = [gregorian components:NSDayCalendarUnit fromDate:fromDate toDate:toDate options:0];
    self.timeDifferenceDay = dayComponents.day;
    NSLog(@"间隔天数:%ld天",(long)dayComponents.day);//间隔的天数
}

方法二:

- (void)takeTimeDifference {
    
    //将时间转换为date
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSDate *applyDate = [self dateFromString:self.model.apply_time];
    NSString *invoiceTimeStr = [self getTomorrowDay:applyDate];
    NSDate *invoiceDate = [formatter dateFromString:invoiceTimeStr];//发票订单时间
    NSDate *nowDate = [NSDate date];//当前时间
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSCalendarUnit type = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;//创建日历
    //利用日历对象比较两个时间的差值
    NSDateComponents *cmps = [calendar components:type fromDate:nowDate toDate:invoiceDate options:0];
    self.timeDifferenceDay = cmps.day;
    NSLog(@"两个时间相差%ld年%ld月%ld日%ld小时%ld分钟%ld秒", cmps.year, cmps.month, cmps.day, cmps.hour, cmps.minute, cmps.second);
}

8.xib设置高度属性

9.通过代码杀死App进程

https://www.jianshu.com/p/36ef8336da50

10.监听UITextfield、UITextView的输入

https://www.jianshu.com/p/2774a86862f5

11.不合法语句 self.contentView.frame.origin.x = x;

下面的写法是错误的:
CGFloat x = self.contentView.frame.origin.x;
x = _lastDownX + translation.x;
self.contentView.frame.origin.x = x;
正确的写法是:
CGRect frame = self.contentView.frame;
frame.origin.x = _lastDownX + translation.x;
self.contentView.frame = frame;

12.UITableViewStyleGrouped的headView和footView的高度设置

设置UITableViewStyleGrouped的头视图和尾视图的时候,在把头视图和尾视图的高度都设置成0的时候没有效果。因为如果把高度设为0的默认值相当于没有高度,设置header或者footer把另一个设置成0 -1之间的数才会有效果。

创建表格-Grouped模式 header footer

13.push跳转实现模态效果

在登录的时候一般都会用模态方式弹出登录页,然后push注册或者找回密码页面,模态再push是很恶心的事情,来回切换还需要再创建一个导航控制器。可以通过利用动画以假乱真,实现push模态效果。
链接:https://www.jianshu.com/p/d360169c77dc

  • push-模态效果
SKLoginViewController *vc = [[SKLoginViewController alloc] init];
// push-转场动画为模态
CATransition *animation = [CATransition animation];
animation.duration = 0.3f;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.type = kCATransitionMoveIn;
animation.subtype = kCATransitionFromTop;
animation.delegate = self;
[self.view.layer addAnimation:animation forKey:nil];
[self.navigationController.view.layer addAnimation:animation forKey:nil];
vc.isNavPush = YES;
[self.navigationController pushViewController:vc animated:NO];
  • pop-模态效果
// pop回去-转场动画为模态效果
- (void)popWithDismissEffect {
    
    CATransition *animation = [CATransition animation];
    animation.duration = 0.3f;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.type = kCATransitionReveal;
    animation.subtype = kCATransitionFromBottom;
    animation.delegate = self;
    [self.view.layer addAnimation:animation forKey:nil];
    [self.navigationController.view.layer addAnimation:animation forKey:nil];
    [self.navigationController popViewControllerAnimated:NO];
}
  • 补充:pop到指定VC

1.pop回根视图控制器

[self.navigationController popToRootViewControllerAnimated:YES];

2.pop到上一级

[self.navigationController popViewControllerAnimated:YES];

3.pop到指定页面(如登录页面)

for (UIViewController *controller in weakSelf.navigationController.viewControllers) {
    if ([controller isKindOfClass:[SKLoginViewController class]]) {
         SKLoginViewController *A =(SKLoginViewController *)controller;
         [weakSelf.navigationController popToViewController:A animated:YES];
     }
}

4.返回指定的某级Nvc用下面2种方法均可(根页面即第0级,从0开始算 )

方法一:
// 第N级;即第N+1个控制器
[self.navigationController popToViewController:
[self.navigationController.viewControllers objectAtIndex:N] animated:YES];
方法二:
// [self.navigationController.viewControllers.count - 3]这个减的结果就是第N级,第N+1个控制器
[self.navigationController popToViewController:self.navigationController.viewControllers[self.navigationController.viewControllers.count - 3] animated:YES];

5.dismissViewControllerAnimated到根视图
https://www.jianshu.com/p/3771161f005f

//把最前面的视图控制器dismiss掉
 UIViewController *parentVC = self.currentVC;
 UIViewController *bottomVC;
 while (parentVC) {
      bottomVC = parentVC;
      parentVC = parentVC.presentingViewController;
 }
 [bottomVC dismissViewControllerAnimated:NO completion:^{//dismiss后再切换根视图
  SKHomeViewController *vc = [SKHomeViewController new];
  SKBaseNavigationController *nav = [[SKBaseNavigationController alloc] initWithRootViewController:vc];
  self.currentVC.view.window.rootViewController = nav;
  [SKToast showWithText:@"登录成功"];
  }];
  • 6. a页面push到b页面,b页面presentViewController到c页面,c如何返回a页面?

解决:在C的back回调中dismiss,同时再发一个通知,在B界面接收通知进行back回调Pop。比如首页push进入到个人中心页面,点击退出Present到登录页面,现在点击登录页面返回的回调想直接回到主页,截图代码如下
https://blog.csdn.net/haoxuhong/article/details/82685569

登录页面返回的回调 个人中心页面接收通知回调
  • 模态方式-满屏*
    设置modalPresentationStyle
    iOS 13.0之前:UIModalPresentationFullScreen
    iOS 13.0之后:UIModalPresentationAutomatic

14.富文本好用的第三方框架

RZColorful;直接pod

15.Jason串解析

有时候后台返回的字段数据是Jason串,这个时候无法直接使用,需要解析转换取到里面的值。

  • 例子
后台返回的为jason串,想要拿到串里面的字符串,则需要解析:
orderListModel.locations.end.station_location = {"lat":"24.579875","lng":"118.101234"}

NSDictionary *dataDict = [NSDictionary dictionaryWithJsonString:orderListModel.locations.end.station_location];
if([dataDict isKindOfClass:[NSDictionary class]]) {
   CLLocationDegrees lat = [dataDict[@"lat"] doubleValue];
   CLLocationDegrees lng = [dataDict[@"lng"]doubleValue];
   dest_lat = lat;
   dest_lng = lng;
}
  • Jason解析方法-字符串转字典
+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString {
   
   if (jsonString == nil ||
       ![jsonString isKindOfClass:[NSString class]]) {
       
       return nil;
   }
   NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
   NSError *err;
   NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];
   
   if(err) {
       NSLog(@"json解析失败:%@",err);
       return nil;
   }
   return dic;
   
}
  • 补充:字典转Jason字符串
NSDictionary *param = @{@"key1":@"value1",@"key2":@"value2"};
NSError *parseError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:param options:NSJSONWritingPrettyPrinted error:&parseError];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

MJ里面也有一个方法:
-(NSstring *)mj_JSONString;

16.当前页面自定义nav隐藏系统nav,下个页面不隐藏

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.navigationController.navigationBar.hidden = YES;
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.navigationController.navigationBar.hidden = NO;
}

17.各个环境的理解

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

18.Sourctree上传Pod之后产生的文件

19.图片压缩方法(知本家)

  • 封装的方法
/// 图片压缩
/// @param originalImage 原图片
/// @param imgWidth 裁剪的宽 默认屏幕宽
/// @param imgHeight 裁剪的高 默认屏幕高
/// @param qualityNum 图片质量设置 默认 1
+ (UIImage *)compressImage:(UIImage *)originalImage andImageWidth:(CGFloat)imgWidth AndImageHeight:(CGFloat)imgHeight andImageQuality:(CGFloat)qualityNum {
    
    CGFloat scaleWidth;
    CGFloat scaleHeight;
    CGFloat widthInPoint;
    CGSize newSize;
    NSData *imageData = UIImageJPEGRepresentation(originalImage, 1.0);
    
    if (imageData.length>2*1024*1024) {
        
          if (imgWidth==0) {
              scaleWidth = [UIScreen mainScreen].bounds.size.width * 2;
              widthInPoint = scaleWidth / [[UIScreen mainScreen] scale];
          } else {
              scaleWidth = imgWidth * 2;
              widthInPoint = scaleWidth / [[UIScreen mainScreen] scale];
          }
          
          if (imgHeight==0) {
              scaleHeight = widthInPoint * originalImage.size.height / originalImage.size.width;
          } else {
              scaleHeight = imgHeight * 2;
              scaleHeight = scaleHeight / [[UIScreen mainScreen] scale];
          }
        
          newSize = CGSizeMake(widthInPoint,scaleHeight);
          UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:newSize];
          UIImage * tempImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
              [originalImage drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
          }];
          tempImage = [UIImage imageWithData:UIImageJPEGRepresentation(tempImage, qualityNum)];
          return tempImage;
    } else {
        return originalImage;
    }
}
  • 举例实际应用
//点击相机方法
- (void)takingPictures {
    [self.imagePicker photographWithController:self selectedAssets:@[] finishPickering:^(NSArray<UIImage *> * _Nonnull photos, NSArray * _Nonnull assets) {
        
        UIImage *image = [UIImage imageWithData:UIImageJPEGRepresentation([photos[0] fixOrientation], 0.5)];
        NSData *fileData = UIImageJPEGRepresentation(image, 1.0);
        
        if (fileData.length >  20 * 1024 * 1024) {
            [MBProgressHUD showError:kLocLanguage(@"txt_JHAddInfoViewController_waringGigMessage") toView:kWindow];
        } else {
            image = [UIImage compressImage:image andImageWidth:0 AndImageHeight:0 andImageQuality:0.5];
            NSVillagePictureFileList *model = [NSVillagePictureFileList new];
            model.chooseImage = image;
            [self.dataArr addObj:model];
            [self.collectionView reloadData];
            [self setAddBtnFram];
        }
    }];
}

20.转菊花延时返回操作

[MBProgressHUD showMessag:kLocLanguage(@"txt_ZXActivateCodeDetailViewController_activeSuccess") toView:self.view andShowTime:1.5];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            
    [self backBtnClicked];
});

21.找到当前的cell-刷新当前cell

//找到当前的cell
NSIndexPath *index = [NSIndexPath indexPathForRow:self.dataArr.count-1 inSection:0];

// 刷新当前cell
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationNone];

22.宽度自适应

123.png

23.xib高度

0A1D9F22FBE8CA42145F0E1BDE3E47D5.jpg 截屏2020-09-28 下午2.43.43.png 截屏2020-09-28 下午2.45.48.png A1D9BB7FB7B1E606A2E17FA4AD6B329E.jpg

24.后台返回的字段错误为数字

如图有时候后台没有处理好,返回的字段名有错误需要注意下。例如后台返回的data里面没返回 public_om_code 这个字段,返回的是public_om_code的code(数字1896017344是public_om_code主体的code),需要后台跳调整一下

25.控制台打印出请求接口的参数、url、结果

宏定义为:#define DLog(...) printf("%s [Line %d] %s\n\n", PRETTY_FUNCTION, LINE, [[NSString stringWithFormat:VA_ARGS] UTF8String])
实用例子:DLog(@"%@",paramsDict);、DLog(@"%@",responseObject);

26. iOS14系统的bug,cell无法点击

因为在iOS14系统下,UITableViewCell添加控件必须添加到它的contentView,直接添加无法点击,上面会有一层遮住。xib画的不影响,xib画的控件就是添加到contentView。
https://www.jianshu.com/p/a01b7aa558e7
解决: UITableViewCell:[self addSubView:]替换成[self.contentView addSubView:];

27.NSString 和 NSMutableAttributedString 如何相互转换

//NSString to NSMutableAttributedString
NSString *aString=@"Hello, world!";
NSMutableAttributedString *attributedString=[[NSMutableAttributedString alloc] initWithString:aString attributes:nil];
[attributedString setAttributes:@{NSForegroundColorAttributeName:[UIColor redColor]} range:NSMakeRange(0, 5)];
//NSMutableAttributedString to NSString
NSString *anotherString=[attributedString string];

28.NSNumber值怎么判断

NSNumber *count = responseObject[@"result"];
if ([count isEqual: @0]) {
//1:主体一致表示可以开 0:主体不一致表示不可开
}

29.请求接口的时候传参数需要传数组的处理

NSMutableDictionary *paramsDict = [[NSMutableDictionary alloc]init];
NSMutableArray *orderNoArr = [NSMutableArray array];
for (InvoiceTravekModel *model in self.orderNoArray) {
    [orderNoArr addObject:model.order_id];
}
[paramsDict setObject:orderNoArr forKey:@"orders"];//传入id的数组
[paramsDict setObject:[SKUserInfo shareManager].userID forKey:@"uid"];
[paramsDict setObject:[SKUserInfo shareManager].userToken forKey:@"access_token"];
NSString *url = [BBXURL domainAppendString:@"/api/invoice/check_time"];

30.多textField页面(tableview)布局,利用model绑定数据

经常用到一个表格视图,比如下单页面,每个cell有一个textField,这个时候如果通过定义取每个cell来操作容易产生滑动的时候或者刷新表格的时候会产生数据丢失错乱及恢复初始值的现象,这个时候最好需要通过模型来绑定数据。
https://www.jianshu.com/p/17621f85d2ef

相关文章

网友评论

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

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