开发问题笔记(七)

目录

1.后台返回数值类型,用字符串接收遇到的问题
2.iOS 从0到1搭建高可用App框架
3.六天完成一个简单APP的全过程
4.iOS个人开发自己的APP
5.block的问题
6.clipsToBounds和masksToBounds的区别
7.在线转模型工具
8.json在线格式化
9.状态栏的使用总结
10.让UITextFiled键盘收起的小方法
11.封装的cell中循环创建控件的注意
12.创建窗口视图时候的bug
13.项目运行手机报错
14.iOS中几种定时器
15.KVC/KVO/NSNotification区分
16.数字转String
17.UITextField填写完以后回调
18.两个字符串做运算
19.cell/视图封装的BOOL判断控件布局
20.加减按钮的实现
21.左右tableView的cell标志符使用
22.self.navigationController退出到指定页面,或者一次性pop出n个页面
23.App的AppIcon设置
24.App的启动页LaunchImage设置
25.iOS检测app进入后台或前台方法
26.App跳转AppStore更新功能
27.利用UISegmentedControl在同一个控制器切换不同的tableView
28.模型中想修改后台返回的字段名字以及有嵌套数组的情况(MJ方式处理)
29.分组数据的处理(数组嵌套数组)
30.在window上添加视图时的注意事项

1.后台返回数值类型,用字符串接收遇到的问题

后台返回一个字段是数值型,前端用字符串进行如下方式接收,出现程序奔溃

开发问题笔记(七)_第1张图片
返回的ttnum为数值类型
开发问题笔记(七)_第2张图片
接收解析数据的方式,奔溃
开发问题笔记(七)_第3张图片
奔溃,打断点返回的类型为数值类型,接收是字符串

备注:(上面问题的2种解决办法)
1.把ttnum用[NSString stringWithFormat:@"%@"]转一下也不会奔溃了
2.如果解析数据用模型方法去解析的话就不会出现这种问题,因为MJ的方法里会自动转化处理,解决这个问题

开发问题笔记(七)_第4张图片
这种方式写就不会奔溃
  • 其他:
开发问题笔记(七)_第5张图片
错误写法奔溃
开发问题笔记(七)_第6张图片
正确写法

2.iOS 从0到1搭建高可用App框架

https://mp.weixin.qq.com/s/BYQCQxyoIpp1aC7e4l6-dg

3.六天完成一个简单APP的全过程

第一天:https://www.jianshu.com/p/006579dba0b2
第二天:https://www.jianshu.com/p/5f6e92611023
第三天:https://www.jianshu.com/p/35bf4a1119d0
第四天:https://www.jianshu.com/p/e78125b91410
第五天:https://www.jianshu.com/p/98a0c9fe3e6e
第六天:https://www.jianshu.com/p/a47f683920f9

4.iOS个人开发自己的APP

http://www.jianshu.com/p/cf73ec9dcf2c

5.block的问题

问题:封装的导航栏中back按钮在封装的视图中通过block回调点击事件报错,会显示内存泄漏好像;但是在外部调用封装的视图的时候去添加按钮事件,不显示报错,运行正常
解答:block会持有对象。你用block的时候它就持有了当前你用到的一些视图,会引起内存泄露。如果你直接把视图的子视图暴露出来就没有这个问题,但是代码的封装性什么的就不怎么样了。选择block,用weakself去弱引用解决内存泄漏

6.clipsToBounds和masksToBounds的区别

clipsToBounds:是类View的属性;是指视图上的子视图;如果设置为yes,则不显示超出父View的部分
masksToBounds:是类CALayer的属性;是指视图的图层上的子图层;如果设置为yes,则不显示超出父View layer的部分

7.在线转模型工具

  • 在线转换地址:http://modelend.com/
开发问题笔记(七)_第7张图片
在线转模型

8.json在线格式化

使用他的主要是什么呢?一美观,其二看数据格式方面

  • 在线地址:https://www.json.cn/

9.状态栏的使用总结

https://www.jianshu.com/p/1dd3a2aec890

10.让UITextFiled键盘收起的小方法

利用代理的相关通知方法,然后进行可编辑与否的设定实现

11.封装的cell中循环创建控件的注意

12.创建窗口视图时候的bug

使用懒加载的时候,第一次调用创建窗口视图时正常,第二次再次点击按钮创建就出现问题,如下图所示。正确的做法是不用懒加载,直接创建调用

开发问题笔记(七)_第8张图片
正常视图
开发问题笔记(七)_第9张图片
bug视图

懒加载代码(不用这种方式):

开发问题笔记(七)_第10张图片
懒加载代码
开发问题笔记(七)_第11张图片
懒加载代码

正确方式:

开发问题笔记(七)_第12张图片
正确方式代码

13.项目运行手机报错

项目运行一个新的手机(之前未跑过也未添加过该设备)报如下错误,可以更换Bundle Identifier尝试

开发问题笔记(七)_第13张图片
开发问题笔记(七)_第14张图片

14.iOS中几种定时器

https://www.jianshu.com/p/21d351116587

15.KVC/KVO/NSNotification区分

https://www.jianshu.com/p/9728be39b306

16.数字转String

UITextField填写的数是字符串转成数字类型,然后提交参数的时候需要再转成字符串

开发问题笔记(七)_第15张图片
图片.png

17.UITextField填写完以后回调

问题:申请借款的时候,当输入的金额小于上面额度的时候就不展示下面的选择担保人,超过就展示。这是在输入完数字之后,通过UITextField填写完的通知,回调接口请求进行判断,这时候务必也要刷新表格才能改变它的cell数量或者高度,而刷新之后产生一个新的问题,之前输的那些数字又因为reload变回初识化状态。所以有个方法就是在刷新完之后再将UITextField的值赋一遍即可

效果:

开发问题笔记(七)_第16张图片
图片.png

开发问题笔记(七)_第17张图片
图片.png

代码:

开发问题笔记(七)_第18张图片
图片.png

18.两个字符串做运算

图片.png
图片.png
开发问题笔记(七)_第19张图片
图片.png

19.cell/视图封装的BOOL判断控件布局

问题:封装一个cell,在cell中想通过一个BOOL值的YES和NO来控制展示不同的控件,如YES时候,cell右边展示UILabel,NO展示UITextField 。这时候需要把控件的布局判断写在重写BOOL set方法里,不要写在初始化的地方(只要有重新布局的地方都要这样)

正确:

开发问题笔记(七)_第20张图片
图片.png

开发问题笔记(七)_第21张图片
图片.png
开发问题笔记(七)_第22张图片
图片.png
开发问题笔记(七)_第23张图片
图片.png

错误:

开发问题笔记(七)_第24张图片
屏幕快照 2018-10-31 下午3.46.08.png

开发问题笔记(七)_第25张图片
屏幕快照 2018-10-31 下午3.46.28.png
开发问题笔记(七)_第26张图片
屏幕快照 2018-10-31 下午3.46.35.png

20.加减按钮的实现

开发问题笔记(七)_第27张图片
屏幕快照 2018-10-26 上午11.31.15.png
开发问题笔记(七)_第28张图片
图片.png

21.左右tableView的cell标志符使用

问题:一个控制器中同时有两个tableView,比如用这个分段控制器,点击分别切换不同表格。如果两个表格想用同一个封装的cell,复用时的cell标志符也要不一样,不然会有问题奔溃

开发问题笔记(七)_第29张图片

22. self.navigationController退出到指定页面,或者一次性pop出n个页面

ios中 viewcontroller的跳转问题,其中有一种方式是采用navigationController pushViewController 的方法,可能会从主页面跳转到了一级页面,又从一级页面跳转到了二级页面,然后从二级页面跳转到了三级页面,依次类推。。等等

  • 1.如果一级一级的返回直接调用就行
[self.navigationController popViewControllerAnimated:Yes];
  • 2.返回根页面用
[self.navigationController popToRootViewController];
  • 3.返回指定的某级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];
  • 4.其他:
    4.1返回指定控制器
//遍历控制器
for (UIViewController *controller in self.navigationController.viewControllers) { 

   if ([controller isKindOfClass:[你要跳转到的Controller class]]) { 

       [self.navigationController popToViewController:controller animated:YES];
    } 
}
  • 4.2一次性pop到上上一级
int index = (int)[[self.navigationController viewControllers]indexOfObject:self]; 
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:(index -2)] animated:YES];

23.App的AppIcon设置

例子里面的29的1x就是29x29,2x就是58x58,3x就是87x87(单位是pt)。注意App上架的时候传的Logo图标是1024x1024。还有APP的这个图标是用直角的,不要用圆角(会出现黑边),苹果会自动切掉圆角

备注:可以通过将1024x1024的图片拖入“Asset Catalog Creator”软件生成一整套的所有有关图标,再把这个生成的文件夹直接拖入项目中的Assets.xcassets即可(原先里面标着AppIcon的先删除)

开发问题笔记(七)_第30张图片
WechatIMG1.jpeg
开发问题笔记(七)_第31张图片
WechatIMG1.jpeg

24.App的启动页LaunchImage设置

每个APP启动的时候,都会看到一张固定的预览图(这里指一般静态,不包含随时更新的动态效果),再进入首页。一般采用4套图片就可以了

开发问题笔记(七)_第32张图片
选择这4套尺寸可以
开发问题笔记(七)_第33张图片
上面4套图相对应尺寸参数
开发问题笔记(七)_第34张图片
创建启动页的一种方式

相关链接:https://www.jianshu.com/p/269b3f10af5d

备注:设置启动页的最简单的方法:直接在项目中点击LaunchScreen.storyboard,放入一张图片。然后设置约束,再设置图片填充模式

其他相关:
启动页 LaunchImage 不显示问题:https://www.jianshu.com/p/e0670ca38bb7
https://www.jianshu.com/p/a5ebbe2706a3

25.iOS检测app进入后台或前台方法

相关链接:http://www.cocoachina.com/ios/20170908/20507.html

开发问题笔记(七)_第35张图片
App检测更新的方法可写在这个地方

26.App跳转AppStore更新功能

场景:苹果商店上的App已经上架最新的版本,用户当前使用的App还是老版本,想通过弹框的方式提示用户去更新App
要点:
1.App端传一个当前版本号和是哪个系统类型(iOS或安卓)给后台
2.后台设定2个版本(大改动情况:强制更新;小改动情况:非强制更新),通过版本号比较判断来进行相应的更新
3.后台设定2个版本号的原因:会有一种情况,用户当前版本号是5.0,App最新版本号是7.0(该版本为非强制更新),中间还有一次大改动的强制更新版本6.0。此时如果没有设定2个版本的话就会出现,用户在7.0可以选择不更新,但是中间6.0版本的大改动就用不了,但又必须得用,所以设定2个版本临界判断。更新的话都是更新到最新版本的

开发问题笔记(七)_第36张图片
App弹框提示更新效果图

模型建立:

开发问题笔记(七)_第37张图片
模型

网络请求:

网络请求
开发问题笔记(七)_第38张图片
网络请求

AppDelegate中处理更新弹框:

开发问题笔记(七)_第39张图片
开发问题笔记(七)_第40张图片
开发问题笔记(七)_第41张图片
开发问题笔记(七)_第42张图片
开发问题笔记(七)_第43张图片
开发问题笔记(七)_第44张图片
开发问题笔记(七)_第45张图片
开发问题笔记(七)_第46张图片
开发问题笔记(七)_第47张图片

27.利用UISegmentedControl在同一个控制器切换不同的tableView

相关链接:https://blog.csdn.net/qq_30070947/article/details/54139275

28.模型中想修改后台返回的字段名字以及有嵌套数组的情况(MJ方式处理)

1.有嵌套数组的情况:
开发问题笔记(七)_第48张图片
UToSpotsModel.h
开发问题笔记(七)_第49张图片
UToSpotsModel.m
开发问题笔记(七)_第50张图片
UToTimeModel.h
开发问题笔记(七)_第51张图片
UToTimeModel.m
2.自定义名字的情况:
开发问题笔记(七)_第52张图片
UToPassenger.h
开发问题笔记(七)_第53张图片
UToPassenger.m

29.分组数据的处理(数组嵌套数组)

返回的数据是嵌套的,分组的形式,主要通过模型的建立来解决问题

开发问题笔记(七)_第54张图片
App效果图
开发问题笔记(七)_第55张图片
后台返回的数据结构图1
开发问题笔记(七)_第56张图片
后台返回的数据结构图2

模型建立(UToDanJuModel):

h文件:
#import 

NS_ASSUME_NONNULL_BEGIN

@interface UTOContentItemModel :NSObject

@property (nonatomic, copy) NSString *order_ttnum;
@property (nonatomic, copy) NSString *order_price;
@property (nonatomic, copy) NSString *client_name;
@property (nonatomic, copy) NSString *client_avatar;
@property (nonatomic, copy) NSString *date;
@property (nonatomic, copy) NSString *client_id;

@end

@interface UTODanJuDataItemModel :NSObject

@property (nonatomic, copy) NSString *showtime;
@property (nonatomic, copy) NSString *date;
@property (nonatomic, strong) NSArray  *content;

@end

@interface UTODanJuModel :NSObject

@property (nonatomic, strong) NSArray  *data;
@property (nonatomic, assign) NSInteger code;
@property (nonatomic, copy) NSString *message;

@end

NS_ASSUME_NONNULL_END
m文件:
#import "UToDanJuModel.h"

@implementation UTOContentItemModel

@end

@implementation UTODanJuDataItemModel

+ (NSDictionary *)objectClassInArray{
    return @{
             @"content" : @"UTOContentItemModel"
             };
}

@end

@implementation UTODanJuModel

+ (NSDictionary *)objectClassInArray{
    return @{
             @"data" : @"UTODanJuDataItemModel"
             };
}

@end

控制器中的相关代码:

1.请求数据:
    NSDictionary *dic = [[NSDictionary alloc]init];
    if (isSelectSouSuoTime == NO) {// 没有选择时间
        
        dic = @{@"token":[UToUser sharedUToUser].token,@"operate_type":@(_operate_type),@"date":@"",@"page":@(pageNum)};
        SXUTONetWorkModel *model = [SXUTONetWorkModel UTONetWorkModelWithUTORequestType:SXUTORequestTypeSaleOrder parmeter:dic];
        if ([self.netWork request:model userToken:nil Identifier:@"SXUTORequestTypeSaleOrder"]) {
            
            self.hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
            self.hud.delegate = self;
        }
    }
2.数组:
@property (nonatomic, strong) NSMutableArray *resultArray;// 搜索结果数组
@property (nonatomic, strong) NSMutableArray *contentArray;

_resultArray = [NSMutableArray array];
_contentArray = [NSMutableArray array];
3.返回数据的处理:
     if (StrSame(identifier, @"SXUTORequestTypeSaleOrder")){
        
        NSArray *array = responseObject[@"data"];
        
        if (pageNum == 1) {// 关键代码
            
            self.resultArray = [UTODanJuDataItemModel mj_objectArrayWithKeyValuesArray:array];// 改填resultArray
            
            for (UTODanJuDataItemModel *item in self.resultArray) {
                
                [_contentArray addObject:item.content];
            }
            
            for (NSArray *itemArray in _contentArray) {
                
                for (UTOContentItemModel *model in itemArray) {
                    
                    NSLog(@"%@", model.client_name);
                }
            }
        } else {
            
            [self.resultArray addObjectsFromArray:[UTODanJuDataItemModel mj_objectArrayWithKeyValuesArray:array]];// 改填resultArray
            
            for (UTODanJuDataItemModel *item in self.resultArray) {
                
                [_contentArray addObject:item.content];
            }
            
            for (NSArray *itemArray in _contentArray) {
                
                for (UTOContentItemModel *model in itemArray) {
                    
                    NSLog(@"%@", model.client_name);
                }
            }
        }
        
        if (array.count >= pageSize) {
            
            pageNum++;
            [self.saleListTableView setIsCanPullUpToLoadMore:YES];
        } else {
            
            [self.saleListTableView setIsCanPullUpToLoadMore:NO];
        }
        
        if (self.resultArray.count<=0) {// 改填resultArray
            
            [self.view addSubview:self.noDataImg];
            self.saleListTableView.hidden = YES;
            self.noDataImg.hidden = NO;
            downLine.hidden = NO;
            [self.saleListTableView setRefreshBtn:RefreshBtnStateNoData];
        } else {
            
            self.saleListTableView.hidden = NO;
            self.noDataImg.hidden = YES;
            downLine.hidden = YES;
        }
        [self.saleListTableView reloadData];
    }
4.表格部分处理:
创建:
- (UToTableView *)saleListTableView {
    
    if (!_saleListTableView) {
        
        _saleListTableView = [[UToTableView alloc]init];
        [self.view addSubview:_saleListTableView];
        _saleListTableView.backgroundColor = [UToColor backgroundGrayColor];
        _saleListTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        _saleListTableView.delegate = self;
        _saleListTableView.dataSource = self;
        _saleListTableView.scrollEnabled = YES;
        [_saleListTableView registerClass:[UToGoodsListSimpleCell class] forCellReuseIdentifier:@"UToGoodsListSimpleCellIdentifier"];
        _saleListTableView.reDelegate = self;
        [_saleListTableView setIsShowRefresh:YES];
        [_saleListTableView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            make.left.right.mas_equalTo(0);
            make.top.mas_equalTo(self.topTitleView.mas_bottom).offset(0);
            make.bottom.mas_equalTo(0);
        }];
    }
    return _saleListTableView;
}

协议代理:
#pragma mark -- UITableviewDelegate && UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    
    return self.resultArray.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
    UTODanJuDataItemModel *model = _resultArray[section];
    return model.content.count;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    return 75;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    
    return 30;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [UToColor grayColor];
    UILabel *titleLB = [[UILabel alloc]init];
    [view addSubview:titleLB];
    titleLB.backgroundColor = [UIColor clearColor];
    titleLB.font = [UToFont defaultAdaptationBoldFontWithSize:14];
    titleLB.textAlignment = NSTextAlignmentCenter;
    UTODanJuDataItemModel *model = _resultArray[section];
    titleLB.text = model.date;
    [titleLB mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.centerX.mas_equalTo(view);
        make.centerY.mas_equalTo((view));
        make.width.mas_equalTo(200);
    }];
    return view;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    UToGoodsListSimpleCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UToGoodsListSimpleCellIdentifier"];
    cell.isNONum = NO;
    cell.isHaveBtn = NO;
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    UTODanJuDataItemModel *sectionModel = _resultArray[indexPath.section];
    UTOContentItemModel *model = sectionModel.content[indexPath.row];
    [cell.headImg sd_setImageWithURL:[NSURL URLWithString:model.client_avatar] placeholderImage:[UIImage imageNamed:@"morenkehu"]];// 占位图
    cell.nameLB.text = model.client_name;
    cell.numLB.text = model.order_ttnum;
    cell.priceLB.text = model.order_price;
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    UToSaleListDetailViewController *VC = [[UToSaleListDetailViewController alloc]init];
    UTODanJuDataItemModel *sectionModel = _resultArray[indexPath.section];
    UTOContentItemModel *model = sectionModel.content[indexPath.row];
    VC.client_id = model.client_id;
    VC.operate_type = _operate_type;
    VC.dateStr = model.date;
    [self.navigationController pushViewController:VC animated:YES];
}

30.在window上添加视图时的注意事项

开发问题笔记(七)_第57张图片

你可能感兴趣的:(开发问题笔记(七))