美文网首页BUG集锦
[iOS] 简单总结下新项目消灭的300多个warning

[iOS] 简单总结下新项目消灭的300多个warning

作者: pingpong_龘 | 来源:发表于2016-06-12 21:11 被阅读662次

    1. 背景

    因为种种原因,当了回接盘侠.
    拿到一个运动类APP, 一打开,我去,编译了好半天,文件大的不得了. 然后就看见那个warning蹭蹭蹭的往上涨.
    等编译完定睛一看,我擦371个warning.

    app_warning.png
    虽然这只是warning,不影响APP的正常运行.
    但是
    且不说,影响编译效率,耗费时间,而且有潜在bug风险,光本着强迫症习惯这一个理由,就足以决定先停下其他事情,把warning清一清.
    否则,根本无心工作啊...

    2. 开始清

    刚好是端午节, 除了第一天陪妹子去无锡玩了一天,剩下两天就耗在这个上面了.
    不过意外在徐汇发现一个不错的图书馆:Instituto Cervantes(塞万提斯图书馆)(就是写堂吉诃德的那个作者),整个清理过程大部分就是在这里完成的:

    2.pic.jpg

    清理完,长呼一口气...

    okey,下面是清理完的截图:

    屏幕快照 2016-06-12 下午8.57.09.png

    polen: 最后一个warning是CocoaLumberjack的自定义一个红开关warning,严格说就不算warning了,暂且忽略之...

    <br >

    3. 回顾下都有哪些warning

    虽然数量很多,但是种类来说,其实就那么几条. 因为里面大部分warning都是C/C++代码的warning,其实对iOS开发的指导意义并不大,这里挑选其中比较有用或者有意义的整理下:

    3.1 方法弃用类

    3.1.1 sizeWithFont

    sizeWithFont

    iOS 7.0以前获取字体所占空间大小的方法,很好用.不过现在弃用了,这个很好改(用新方法:boundingRectWithSize):

    官方说明

    - (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode 
    NS_DEPRECATED_IOS(2_0, 7_0, "Use -boundingRectWithSize:options:attributes:context:") __TVOS_PROHIBITED; 
    // NSTextAlignment is not needed to determine size
    

    FIX:

    写了个NSString的Category,里面实现了boundingRectWithSize,所有用到的地方直接调用这个就可以了.

    - (CGSize)sizeOfFont:(UIFont*)font andWidth:(float)width {
      NSDictionary* attribute = @{NSFontAttributeName : font};
    
      CGSize retSize =
          [self boundingRectWithSize:CGSizeMake(width, 9999999)
                             options:NSStringDrawingTruncatesLastVisibleLine |
                                     NSStringDrawingUsesLineFragmentOrigin |
                                     NSStringDrawingUsesFontLeading
                          attributes:attribute
                             context:nil]
              .size;
    
      return retSize;
    }
    

    <br >

    3.1.2 NSDateComponents.week

    week

    做过日历的童鞋肯定懂,关于NSDateComponents的week,新增了weekOfMonth or weekOfYear,以前直接调用week的方法弃用了.

    官方说明

    - (NSInteger)week 
    NS_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use weekOfMonth or weekOfYear, depending on which you mean");
    - (void)setWeek:(NSInteger)v 
    NS_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use setWeekOfMonth: or setWeekOfYear:, depending on which you mean");
    

    这个改起来稍微麻烦一点,也还好,这个是在显示时间的地方(显示类似"3周前")代码里使用了
    NSDate+Helper这个开源库,但是源码Github上找不到了,
    随徒手改之:

    FIX:

    - (NSInteger)weeksFrom:(NSDate*)date calendar:(NSCalendar*)calendar {
      if (!calendar) {
        calendar = [[self class] implicitCalendar];
      }
    
      NSDate* earliest = [self earlierDate:date];
      NSDate* latest = (earliest == self) ? date : self;
      NSInteger multiplier = (earliest == self) ? -1 : 1;
      NSDateComponents* components = [calendar components:NSCalendarUnitWeekOfYear
                                                 fromDate:earliest
                                                   toDate:latest
                                                  options:0];
      return multiplier * components.weekOfYear;
    }
    

    <br >

    3.2 Directory not found for option ...

    not found

    这个是编译时找不到对应的framework,可能这个framework你已经不用了,但是Search Paths 没有清除掉.在build setting->Framework Search Paths 删除掉你Not found的目录即可.

    屏幕快照 2016-06-12 下午5.03.59.png

    参照:
    消除 Xcode7 中 directory not found for option 'xxxx' 警告
    Apple Developer: warning: directory not found

    <br >

    3.3 The app icon set "AppIcon" has an unassigned child

    The app icon set

    这个是images.scassets 出了问题,找到你的AppIcon,删除掉Unassigned的图片即可,(如果是空的也要删除)

    AppIcon Unassigned

    参照:
    http://stackoverflow.com/questions/29433670/app-icon-has-unassigned-image-error

    <br >

    3.4 'kCFStreamSSLAllowsExpiredCertificates' is deprecated: fitst deprecated in iOS 4.0

    kCFStreamSSLAllowsExpiredCertificates

    官方说明

    kCFStreamSSLAllowsExpiredCertificates:
    kCFStreamSSLAllowsExpiredRoots:
    kCFStreamSSLAllowsAnyRoot:

    The SSL handshake flags which affect untrusted certificate chain evaluation are deprecated. Instead, use the single property kCFStreamSSLValidatesCertificateChain to disable certificate chain checking if the user has decided that it is appropriate to do so
    So the simple solution is to remove the deprecated keys and their values. Keep only kCFStreamSSLValidatesCertificateChain and kCFStreamSSLPeerName in the sslProperties dictionary.

    这个代码没有用AFNetwork,用的是ASIHttpRequest(看来也是代码比较长久了...)
    kCFStreamSSLAllowsExpiredCertificates已经弃用了.

    FIX:

    方案A: 移除掉就可以了.

    NSDictionary* sslProperties = [[NSDictionary alloc]
          initWithObjectsAndKeys:[NSNumber numberWithBool:NO],
                                 kCFStreamSSLValidatesCertificateChain, kCFNull,
                                 kCFStreamSSLPeerName, nil];
    

    方案B: 加一条
    #pragma clang diagnostic ignored "-Wdeprecated-declarations".

    参照:

    <br >

    3.4 'delete' applied to a pointer that was allocated with 'new[]';did you mean 'delete[]'?

    delete[]

    这是c++的代码,delete删除的时候,如果对象是new[]出来的,对应删除需要采用delete[].这个估计是当时写代码的家伙手抖了,笔误...

    polem:
    记住规则:malloc/free, new/delete, new[]/delete[])

    官方说明

    In the first alternative (delete object), the value of the operand of delete shall be a pointer to a non-array object or a pointer to a sub-object (1.8) representing a base class of such an object (clause 10). If not, the behavior is undefined.
    In the second alternative (delete array), the value of the operand of delete shall be the pointer value which resulted from a previous array new-expression. If not, the behavior is undefined.

    delete :
    calls the appropriate destructor only for the element pointed to (if needed), then frees the memory chunk
    delete[] :
    calls the appropriate destructors for each element in its array (if needed), then frees the memory chunk

    参照:
    http://stackoverflow.com/questions/4255598/delete-vs-delete

    FIX:

    delete[] session_info_buf;
    

    <br >

    3.5 'Register' storage class specifier is deprecated

    Register' storage class specifier

    register作为关键字修饰的变量,意思其修饰的变量可能会被频繁调用,所以期望保存在CPU的寄存器中(一般都是存在堆或者栈之中),这样可以加快处理速度.(补充:标识符的类型知识可以看这里

    但是如今的编译器并不会太理会这些东西,所以有点"然并卵"的即视感. 后来,C++17中直接给弃用掉了.

    屏幕快照 2016-06-12 下午6.20.50.png
    链接:
    http://en.cppreference.com/w/cpp/language/storage_duration

    FIX:

    方案A:直接删掉register就好了

    int myrandom32() {
      if (_rg.Null()) {
        int a;
        int b;
        tUInt32 c;
    ...
    

    方案B:
    忽略掉这个警告,-Wdeprecated-register

    #pragma clang diagnostic ignored "-Wdeprecated-register"
    

    参照这里:http://stackoverflow.com/questions/22422741...

    <br >

    3.6 Automatic Preferred Max Layout Width before iOS 8.0

    Automatic Preferred Max Layout Width

    瞧瞧,瞧瞧,多少这种warning,这种就是,在做layout 的时候,设置了labe的numberoflines 是0, 但是没设置Preferred Width导致的.当然这里面有个比较麻烦的时候,如果xib有多个label,逐个去找哪个没设置,是比较耗费时间和精力的,但是xcode的warning又没有详细的告诉你是哪个label出问题了(很不人性化),所以需要看Source Code里的id对应到label 的Object Id,具体看这里:
    To Find the problem label(s) in a large storyboard...

    Fix:

    屏幕快照 2016-06-12 下午6.06.16.png

    <br >

    3.7 ignore waning

    其他很多warning是c代码里面的,unused或者类型不对的,什么long和int或者unsigned int等等,这些没啥技术含量,逐个修改就好了.

    最后还有一个万能方法是:如果你已经百分百确定这个文件的warning不用修复,百分百确定是安全的,那么你可以忽略这个警告.

    (如果有些同学是从MRC 过度到ARC的,那就知道这里(设置-fno-objc-arc的地方))
    加一个-w即可

    Target->Build Phases->Compile Sources->对应的文件

    -w

    <br >


    by polen

    相关文章

      网友评论

      • 洁简:有些第三方库支持低版本,但是我们的应用不支持,这样产生的版本警告该怎么消除呢?
      • Nemocdz:我们项目9999+ warning:cry:
      • 清眸如画:第二张图就深深的吸引了我 :smile:
        pingpong_龘:@约定一生 :stuck_out_tongue_winking_eye:

      本文标题:[iOS] 简单总结下新项目消灭的300多个warning

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