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

开发问题笔记(二)

作者: Kevin_wzx | 来源:发表于2019-02-25 17:58 被阅读0次

    目录

    1.代码合并注意
    2.布局出错
    3.自定义cell
    4.自定义字体
    5.“OBJC_CLASS$_UToPassenger” refernced from
    6.xcode奇葩问题
    7.数组排序问题
    8.cell层的结构
    9.取消ios自带的侧滑返回的手势
    10.模型的使用
    11.因为hud的问题造成的巨坑
    12.打印iphone设备奔溃日志
    13.保存当前分支的项目
    14.测试与线上的区别
    15.Model问题
    16.布局小问题
    17.网络数据请求注意
    18.使用const注意
    19.使用sourceTree管理代码时
    20.有时候程序报错,但是点击红点跳不到解释错的页面
    21.Xib与代码的结合例子
    22.创建控件初始化
    23.类方法使用
    24.UI界面用的单位(iOS)
    25.杂
    26.手机首次运行项目
    27.添加自定义字体
    28.我的页面的广告页显示问题
    29.每次做断点调试的时候,怎么打印出当前请求的接口及参数的完整链接
    30.使用懒加载的好处-->数组举例

    1.代码合并注意

    1.先提交自己的,注明提交更改的内容以方便查询
    2.再合并队友的,然后运行看下是否有错,有就改错
    3.保证无错误后再推上去

    2.布局出错

    问题:在九宫格版本的消息中心界面,表格视图超出范围,导致拉不到低。是因为布局时的参照物以消息中心下边沿为准,所以要减去那一段高度,或许还要再减去导航栏高度,看具体情况

    [_informationTableView mas_makeConstraints:^(MASConstraintMaker *make) {
            
           make.left.mas_equalTo(0);
           make.right.mas_equalTo(0);
           make.top.mas_equalTo(0);
           make.height.mas_equalTo(SCREEN_HEIGHT-46-64);
    }];
    

    3.自定义cell

    自定义表格cell时,如果多个地方用到相同的,又有一些不同,则可以定义一个bool值来进行不同的展示。注意:在创建cell的时候,设置的bool不能放在创建cell的if里面;如:

    if (!_placeCell) {
                        
         _placeCell = [[UToPlaceCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UToPlaceCellIdentifier"];
     }
     _placeCell.isScanCode = YES;//放在if里面则是NO
    

    4.自定义字体

    http://blog.csdn.net/qqaniu/article/details/16364501

    5.“OBJC_CLASS$_UToPassenger” refernced from

    问题解决方法:http://blog.csdn.net/azhou_hui/article/details/18312047

    6.xcode奇葩问题

    问题:xcode中在 UToFillCampBusOrderFormViewController.m(指出现问题的界面)界面往下拉,拉到一定程度xcode就出现类似奔溃的问题,回到顶部,点击不了,滚动不了。此时只能点其他界面再切换回来可以点击,但滚动到一定程度又重返之前的问题。

    解决方案:将工程Clean一下;然后将编译的数据删除(xcode — preferences — Locations — Derived Data — 点击第一个小箭头 — 看到编译的数据[Xcode文件 — DerivedData文件 — 删除这里面的数据])即可


    屏幕快照 2017-08-31 上午11.18.48.png

    7.数组排序问题

    项目问题场景:

    乘车联系人页面,如果是儿童票入口选票时,联系人按返回的类型排列,儿童票排最前面,其他排后面。child:0为成年
    、1为儿童、2为未成年

    效果图:

    屏幕快照 2017-12-13 下午5.35.37.png
    方法1:快速枚举for in
    方法2:数据模型sortedArrayUsingDescriptors排序
    屏幕快照 2017-12-13 下午5.09.51.png

    扩展备注:sortedArrayUsingDescriptors & sortUsingDescriptors

    前者带返回值,是NSArray的方法,排好序的数组是返回值中的数组;后者不带返回值,是NSMutableArray的方法,是对当前数组自己排序。
    举例:根据一个对象的属性,排列这个对象

    .h

    @interface Person : NSObject
    @property (nonatomic, retain) NSString  *name;
    @property (nonatomic, assign) NSInteger  age;
    @end
    

    .m

    @implementation Person
    
    @end
    

    调用:排序方法的实现

    Person *person1 = [[Person alloc] init];
    person1.name = @"Loki";
    person1.age = 25;
    
    Person *person2 = [[Person alloc] init];
    person2.name = @"Mike";
    person2.age = 22;
    
    Person *person3 = [[Person alloc] init];
    person3.name = @"Larry";
    person3.age = 33;
    
    NSMutableArray *array = [NSMutableArray arrayWithObjects:person1, person2, person3, nil];
    
    (1)不可变数组的处理方法
    //这里类似KVO的读取属性的方法,直接从字符串读取对象属性,注意不要写错
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
    //这个数组保存的是排序好的对象
    NSArray *tempArray = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
    
    for(NSInteger i = 0; i < [tempArray count]; i++) {
    
        NSLog(@"%@--------%d\n", [[tempArray objectAtIndex:i] name], [[tempArray objectAtIndex:i] age]);
    }
    
    (2)可变数组的处理方法   
       [array sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
       
       for(NSInteger i = 0; i < [array count]; i++)  {
    
          NSLog(@"%@--------%d\n", [[array objectAtIndex:i] name], [[array objectAtIndex:i] age]);
      }
    

    比较多个元素的情况:这里的NSArray中的第一元素表示首先按照这个元素的升序或者降序进行排序,对于有重复项的,再按照第二元素进行排序,依次进行类推

    NSSortDescriptor *sortDescriptor1 = [NSSortDescriptorsortDescriptorWithKey:@"age"ascending:YES];
    
    NSSortDescriptor *sortDescriptor2 = [NSSortDescriptorsortDescriptorWithKey:@"name"ascending:YES];
    
    NSArray *tempArray = [array sortedArrayUsingDescriptors:[NSArrayarrayWithObjects:sortDescriptor1, sortDescriptor2, nil]];
    
    方法3:block排序(系统方法)
    屏幕快照 2017-12-14 下午3.55.56.png

    注意:NSArray的排序方法是生成一个排好序的新数组。NSMutableArray的排序可以直接对该数组进行排序sortUsingComparator:,也可以生成新数组sortedArrayUsingComparator: ,而原数组不变。
    sortedArrayUsingComparator这个方法本身就是按递增的方式排序

    sortUsingComparator
    例子1:


    屏幕快照 2017-12-14 下午3.58.01.png 屏幕快照 2017-12-13 下午5.02.27.png 屏幕快照 2017-12-13 下午4.46.22.png

    例子2:


    屏幕快照 2017-12-14 下午3.41.41.png

    sortedArrayUsingComparator


    屏幕快照 2017-12-14 下午2.51.35.png
    方法4:sortedArrayUsingSelector(SEL排序)

    是最简单的排序方式,数组是按照你存入元素的顺序存储的。
    sortedArrayUsingSelector:方法是生成一个排好序的数组并返回;
    sortUsingSelector:方法是直接对原数组进行排序(当然,这个数组要是可变数组,不可变数组没有这个方法)

    (1)sortedArrayUsingSelector


    屏幕快照 2017-12-14 下午3.27.54.png

    compare:是系统的方法


    屏幕快照 2017-12-14 下午3.27.36.png

    (2)我们可以自己实现一个sortUsingSelector:方法


    屏幕快照 2017-12-14 下午3.36.43.png
    屏幕快照 2017-12-14 下午3.37.22.png

    8.cell层的结构

    问题场景:封装的cell视图中在底边加了一条下划线(UIView),线的布局是(0., 65., SCREEN_WIDTH, 1.),外边的cell高度是65(已关闭系统下划线);问题是刚进入视图时能看到线,滑动的时候线就不见了,原因是刚进入视图时cell的展示结构是从下往上,上面cell压下面,下面cell所显示的线其实刚好是上面cell的,最后一个不显示;后面滑动刷新时是从上往下,上面cell的线就刚好被下面cell的线挡住了,就不见了。如下图:

    屏幕快照 2017-12-20 上午10.38.19.png 屏幕快照 2017-12-20 上午10.39.13.png

    9.取消ios自带的侧滑返回的手势

    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
    http://blog.csdn.net/jasonblog/article/details/28282147

    10.模型的使用

    问题:直通车需求:“服务提供方provider”这个Label没有的时候则将其隐藏掉,有则显示;在cell控制高度处判断即可,但是如何做到对应的每个cell呢?(用模型对应)如下:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        
        UToCampusBusTicketsModel *model = _searchResultDataSource[indexPath.section];
        return model.provider.length?176:133;
    }
    

    11.因为hud的问题造成的巨坑

    问题1:删除联系人页面,删掉第一个人正常,在再删除一个人之后全部联系人都删除了,跳出界面再进来发现实际没有删掉,原因是方法[weakSelf.hud hideAnimated:NO]; 没有隐藏,所以出了问题;解决方法就是hideAnimated:NO

    屏幕快照 2017-07-31 下午9.38.42.png

    问题2:司机端强制300问题,开始行程后杀死app,然后再进入界面此时会强跳两次界面,因为mjRefresher问题还是hud问题,以后类似的要注意

    12.打印iphone设备奔溃日志

    Window --- Devices --- 选中iphone --- 点击View Device Logs ,可看到图二就是各种日志...


    屏幕快照 2017-08-22 下午6.07.29.png 屏幕快照 2017-09-01 上午10.33.09.png

    13.保存当前分支的项目

    描述:在SourceTree中项目有多个分支,有的时候想查看之前老分支(老版本)的代码,这时候就要切换分支,比价麻烦,方便的做法就是保存每个分支的项目工程,要用要比对代码时打开就ok了,如何保存当前分支的工程呢?

    解决:打开SourceTree,右上方有个在Finder中显示,点击即可打开该分支下项目的所在位置,然后复制该项目,到其他相放的地方粘贴即可保存成功。

    屏幕快照 2017-09-01 上午11.06.20.png

    14.测试与线上的区别:

    如果是直接运行真机,则选择run里面选择对应的;如果是打包,则在Archive里面选择
    测试:用debug
    线上:用release

    屏幕快照 2017-03-22 上午9.53.32.png 屏幕快照 2017-05-26 下午10.21.12.png

    15.Model问题

    问题:自定义cell时,cell中的各个UILabel的值用模型映射,然后在外部调用这个cell时,将外部解析后有数据的模型赋值给cell的模型,这时要注意:不要在封装的cell中去初始化模型,因为外部赋值的时候相当于初始化了的,否则UI上会出现没有值的情况

    16.布局小问题

    屏幕快照 2017-09-13 下午4.10.56.png

    17.网络数据请求注意

    报错奔溃等问题可以从以下进行排除:

    1.检查接口地址是否正确,有时后台粗心,最前面少了一个/,平常都有;如错误:utoo/order/emptyorder/time/slot 多一个/一般不影响,少了不行
    注意:有时接口写成例子形式:/utoo/order/startsitelist?mode=SHARE&destSiteId=20001 应该取问号前面部分,后面是举例带的参数,注意不要犯这种低级错误

    2.检查参数是否正确:
    1.形式是否正确:是否是用字典(多参数一般都是这样)、model.supplyPath、字典是否需要转成SBJSON形式
    2.参数名字是否填对,与后台给的一致
    3.传的参数没有赋值,为空导致程序奔溃

    3.服务器是否将接口部署完成
    如果没有,就会有错。前面两条方法的使用前提是服务器已经将接口部署完成

    先检查传参数了否?参数等写的形式正确?开发环境的IP地址是否与服务器一致?服务器的接口是否改变或是写错了?

    Http状态码:
    200:请求成功
    300:服务器根据请求可执行多种操作。服务器可根据请求者 来选择一项操作,或提供操作列表供其选择。 如300强制操作
    400:请求错误,由于语法格式有误,服务器无法理解此请求
    401:一般表示需要登录或者登录失败
    403: 服务器拒绝请求(禁止)
    404:找不到 Web 服务器找不到您所请求的文件或脚本,请检查URL 以确保路径正确;也就是后台的接口问题(也有可能接口做好了但没有部署上去)
    405:不允许此方法对于请求所标识的资源,不允许使用请求行中所指定的方法。请确保为所请求的资源设置了正确的 MIME 类型
    500:服务器的内部错误。Web 服务器不能执行此请求。请稍后重试此请求
    根据后台返回的数据来确定建模型;然后解析数据填充UI

    18.使用const注意

    屏幕快照 2017-03-23 下午2.16.54.png
    全局变量,注意不要其他地方定义也用同一个名字,程序会奔溃。
    http://www.jianshu.com/p/f83335e036b5

    19.使用sourceTree管理代码时

    1.合并出错,回滚代码,找到合并之前的分支,然后回滚

    屏幕快照 2017-09-06 下午4.48.04.png

    2.版本已封,但是又改新东西,则可以在相应分支上新建一个分支出来更改,新建如图

    屏幕快照 2017-09-06 上午10.38.53.png

    3.冲突时,如果全部由一个地方更改引起的则可以

    Replace first file with Third : 用第三替换第一个文件
    Replace...with...是用后面的替换掉前面的


    屏幕快照 2017-07-26 下午9.32.55.png

    20.有时候程序报错,但是点击红点跳不到解释错的页面,则可以如下操作

    屏幕快照 2017-09-08 下午5.26.52.png

    21.Xib与代码的结合例子

    自定义的视图是用frame布局,那么使用的时候最好用frame,用其他的可能出现问题
    情况:xib画好的视图,在搜索框与表格视图中插入一个历史行程视图,插入视图用方法:
    [self.view insertSubview:historyView belowSubview:self.indexView]

    A addSubview B  是将B直接覆盖在A的最上层
    A insertSubView B AtIndex:2 是将B插入到A的子视图index为2的位置(最底下是0)
    A insertSubView B aboveSubview:C  是将B插入A并且在A已有的子视图C的上面
    A insertSubView B belowSubview:C  是将B插入A并且在A已有的子视图C的下面
    

    22.创建控件初始化

    创建控件的时候最好都要if(!控件)在这里面创建,加上这个判断,否则容易出现问题,每次都去创建;比如在一键求助与失物找寻按钮的标题重复问题(从定位界面那个地方跳转过来)

    租车开始时间:
           if (!_startTimeCell) {
                
            _startTimeCell = [[SXMDefultCell alloc] init];
            _startTimeCell.appearUnderline = YES;
            _startTimeCell.lineToleftSpace = YES;
            _startTimeCell.lintTorightSpace = YES;
            _startTimeCell.selectionStyle = UITableViewCellSelectionStyleNone;
            _startTimeCell.mainLabel.text = @"起租时间";
            _startTimeCell.isShowAllow = YES;
            }//把下面的if包含进来会出问题,数据无法显示,考虑一下为什么?
            if (self.rentCarInfo.leaveTime) {
                
                _startTimeCell.subLabel.text = [SXTool dateString8WithDate:self.rentCarInfo.leaveTime];
            }else{
                
                _startTimeCell.subLabel.text = @"请选择起租时间";
            }
            
            if (StrSame(_startTimeCell.subLabel.text, @"请选择起租时间")) {
                
                _startTimeCell.subLabel.textColor = [SXTool grayColor];
            } else {
                
                _startTimeCell.subLabel.textColor = [SXTool blackColor];
            }
         [_startTimeCell layoutView];
         return _startTimeCell;
    

    23.类方法使用

    用类方法创建初始化(封装顺风车的订单视图,做判断分别布局);写法如下

    + (instancetype)initWithFrame:(CGRect)rect IsSimple:(BOOL)isSimple {
        
        UToTripOrderView *tripVC = [[UToTripOrderView alloc] initWithFrame:rect];
        tripVC.isSimple = isSimple;
        
        if (isSimple == NO) {
            
            [tripVC creatUI];
            [tripVC layoutSubviewsOne];
        } else if (isSimple == YES) {
            
            [tripVC creatUI];
            [tripVC layoutSubviewsTwo];
        }
        return tripVC;
    }
    

    24.UI界面用的单位(iOS)

    1.pt:ios开发单位,即point。UI标多少就写多少;1pt=1/163英寸
    2.px:即为我们所说的像素,是物理屏幕显示的基本单位,转化为px然后显示在我们的手机上
    3.ppi:Pixels Per Inch(像素密度),表示沿着对角线,每英寸所拥有的像素(pixel)数目,PPI的数值越高,代表显示屏能够以越高的密度显示图像,即通常所说的分辨率越高,颗粒感越弱,图像更清晰

    4.@1x、@2x、@3x: scale factor,缩放因子;scale=绝对长度比(point/pixel)=单位长度内的数量比(pixel/point)

    5.屏幕尺寸:指的是显示屏的对角长度,以下为iPhone5s、iPhone6s、iPhone6Plus屏幕尺寸规格示意图:


    20161011154252609.png

    换算:

    屏幕快照 2017-09-29 上午11.39.18.png 20170415102134179.png 屏幕快照 2017-09-29 上午11.33.55.png
    发展: 屏幕快照 2017-09-29 上午11.17.11.png
    后来从iphone4开始改变的原因是因为:Retina显示技术
    尺寸: 屏幕快照 2017-09-29 上午11.42.57.png

    注意:如果我们想要坐到完美适配,同一个图片必须要做@1x,@2x,@3x三种,这三种类型的长度的比例为: @3x为三倍的@1x 、 @2x为两倍的@1x

    **相关链接: iPhone屏幕尺寸、分辨率及适配 **
    http://blog.csdn.net/phunxm/article/details/42174937

    25.杂

    1.按钮的回调、block里可以传任意值,不一定是传按钮
    2.字符串转CGFloat 类型:floatValue
    3.[cell setSelectionStyle:UITableViewCellSelectionStyleNone];// 选中单元格效果
    _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;// 去掉分割线

    26.手机首次运行项目

    当新手机第一次在项目上运行时,需要注册;连接手机之后,自动弹出如下所示的提示框,点击Register Device即可

    屏幕快照 2017-10-10 下午5.28.19.png

    27.添加自定义字体

    第一步:下载文件并拖入到项目中(或UI下载提供)
    第二步:plist文件中添加键
    第三步:封装的类中根据需要填写相应的字体类型

    屏幕快照 2017-10-17 上午11.15.03.png 屏幕快照 2017-10-17 上午11.15.24.png 屏幕快照 2017-10-17 上午11.16.00.png 屏幕快照 2017-10-17 上午11.14.39.png 屏幕快照 2017-10-17 上午11.14.48.png

    28.我的页面的广告页显示问题

    问题描述:在我的当前页面,点击登录显示底部广告页,点击退出按钮正常隐藏广告页;切换底部分栏按钮,再点击跳到我的页面,此时在登录状态退出登录,可以正常退出,但是广告页还在

    原因分析:还在的广告页其实是上一次初始化创建的,当前的广告页视图已经隐藏了,所以点击还在的广告页的分享回调方法不响应(只在登录状态有);这是因为第一次创建时指针指向还在的那个广告页,第二次创建就指向当前的这个广告页,当退出登录隐藏了,内存释放了当前的广告页,但是还在的那个广告页没有释放所以还在,最本质的原因是创建时没有在非的状态(也就是没有时才创建)创建(又在viewWillAppear里创建),所以每次一直叠加。所以创建控件的时候,最好都在非的状态下去创建。_bottomShareImgView是广告页
    if (!_bottomShareImgView) {
    。。。。。。
    }

    下面是错误的情况的截图:


    29.每次做断点调试的时候,怎么打印出当前请求的接口及参数的完整链接

    WechatIMG60.jpeg WechatIMG20.jpeg

    30.使用懒加载的好处-->数组举例

    场景说明:加载客户列表数据,删除客户成功之后需要再次调用客户列表数据,这个时候需要做个关键的操作,先把数组清空,然后再加载列表数据,这样重新得到的数组里数据个数才是正确的。(不然没删除就加载还会是之前缓存的数组,也就是实际删除了的,但是这个时候拉回来的数组里装的数据会是包含了删除的,再下拉一次加载列表才清空,得到正确的数组个数;这个跟搜索时先清空数组的原理一样),可以不删除数组的做法就是直接数组用懒加载形式创建,这样需要的时候才会调用,不会有缓存啥的
    有的时候不用懒加载,不先清空数据也不会有错,比如删除李管家员工的操作,但是最好还是先清空(不太确定是否跟后台接口有关,这里自己做个记录)

    客户列表

    相关文章

      网友评论

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

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