美文网首页iOS 开发技巧错误集锦学习封装的demo材料
新瓶装老酒,用宏来快速消除Xcode警告

新瓶装老酒,用宏来快速消除Xcode警告

作者: wwwbbat | 来源:发表于2017-07-07 10:42 被阅读86次

    当我们没有新需求时,就会手痒痒要消除项目中的警告,即不会太无聊,又不会让boss觉得你很闲😂。
    如何消除Xcode警告,想必大家见过不少文章了。总结起来,大体上有以下几种方法:

    1:编译器警告的代码确实有问题,那就修改代码消除。
    2:代码中使用 #pragma 预编译指令消除指定类型的警告。
    3:在Compile Sources列表中,对某个文件添加消除指定警告的CompileFlags
    4:使用cocoapods管理时可以指定消除全部的警告或者指定消除某个库的警告。
    5:在Build Setting中搜索Warning,可以通过各个警告类型的开关,来控制全局的警告提示。
    

    今天在这里研究第二种方法,通过宏:

    NO_WARNING_BEGIN(-Wundeclared-selector)
    NO_WARNING_END
    

    来代替如下长长的预编译指令。

    #pragma clang diagnostic push
    #pragma clang diagnostic ignored -Wunused-function
    //code
    #pragma clang diagnostic pop
    

    先亮宏定义:

    // 这几个宏不要直接使用
    #define N_W_MACRO_CAT(a,b)  a b
    #define N_W_MACRO_STR_(text) # text
    #define N_W_MACRO_STR(text) N_W_MACRO_STR_(text)
    #define N_W_MACRO_PREFIX_   clang diagnostic ignored
    #define N_W_MACRO_PREFIX    N_W_MACRO_PREFIX_
    #define N_W_MACRO_(text)    N_W_MACRO_CAT(N_W_MACRO_PREFIX,N_W_MACRO_STR(text))
    #define N_W_MACRO(text)     N_W_MACRO_STR(N_W_MACRO_(text))
    
    //下面就是消除警告开始宏
    #define NO_WARNING_BEGIN(text)\
        _Pragma("clang diagnostic push")\
        _Pragma(N_W_MACRO(text))
    //下面就是结束消除警告宏
    #define NO_WARNING_END \
        _Pragma("clang diagnostic pop")
    

    使用方法:

    // 使用消除警告宏消除警告
    NO_WARNING_BEGIN(-Wunused-function)
    NO_WARNING_BEGIN(-Wundeclared-selector)
    NO_WARNING_BEGIN(-Warc-performSelector-leaks)
    
    // 不消除警告时,Xcode会在这一行显示警告:Unused function 'test2'
    static void test2(void){
      id obj = [NSObject new];
      // 不消除警告时,Xcode会在这一行显示警告:Undeclared selector 'theSELName'
      SEL aSEL = @selector(theSELName);
      if ([obj respondsToSelector:aSEL]) {
        // 不消除警告时,Xcode会在这一行显示警告:PerformSelector may cause a leak because its selector is unknown
        [obj performSelector:aSEL];
      }
    }
    //警告结束,后面的代码可以继续出现警告
    NO_WARNING_END
    

    原理就是:使用 _Pragma 代替 #pragma。通过一系列字符拼接将两行预编译指令压缩到一个宏中。
    有人会问了,这样做有什么好处呢?也就少了一行代码而已。😬
    那么我就说一个好处:宏有代码提示😝,仅此而已。大家把常用的警告类型也做成宏,那就括号内的内容也有提示了。

    附上源码:

    //
    //  Warning.h
    //  CDT
    //
    //  Created by wwwbbat on 2017/7/6.
    //  Copyright © 2017年 . All rights reserved.
    //
    
    #ifndef Warning_h
    #define Warning_h
    
    // 不要修改下面的宏
    #define N_W_MACRO_CAT(a,b)  a b
    #define N_W_MACRO_STR_(text) # text
    #define N_W_MACRO_STR(text) N_W_MACRO_STR_(text)
    #define N_W_MACRO_PREFIX_   clang diagnostic ignored
    #define N_W_MACRO_PREFIX    N_W_MACRO_PREFIX_
    #define N_W_MACRO_(text)    N_W_MACRO_CAT(N_W_MACRO_PREFIX,N_W_MACRO_STR(text))
    #define N_W_MACRO(text)     N_W_MACRO_STR(N_W_MACRO_(text))
    
    #define NO_WARNING_BEGIN(text)\
        _Pragma("clang diagnostic push")\
        _Pragma(N_W_MACRO(text))
    
    
    #define NO_WARNING_END \
        _Pragma("clang diagnostic pop")
    
    // 不要修改上面的宏
    
    // 用法与示例
    
    // 请将 WARNING_DEMO 设为 1 打开示例
    #define WARNING_DEMO 0
    
    #if DEBUG && WARNING_DEMO
    
    /*
     正常情况下,test1会有三个警告:
     a: Unused function 'test1'
     b: Undeclared selector 'theSELName'
     c: PerformSelector may cause a leak because its selector is unknown
    
     按 command + 5 打开警告列表。找到a,b,c对应的警告,右键选择 Reveal in log。
     可以看到这样的文本:
     Common/Warning.h:51:17: warning: undeclared selector 'theSELName' [-Wundeclared-selector]
     SEL aSEL = @selector(theSELName);
     ^
     /Users/jay/iOS/CDT/CDT/CDT2017/Common/Warning.h:54:14: warning: performSelector may cause a leak because its selector is unknown [-Warc-performSelector-leaks]
     [obj performSelector:aSEL];
     ^
     Common/Warning.h:48:13: warning: unused function 'test1' [-Wunused-function]
     static void test1(void){
     ^
     其中可以找到
     a 的警告类型:-Wunused-function
     b 的警告类型:-Wundeclared-selector
     c 的警告类型:-Warc-performSelector-leaks
    
     在发出警告的代码前使用消除警告代码宏即可消除这些警告。
     忘了在消除了警告的代码之后使用结束宏。消除开始宏可以写多个。结束宏只需要写一个就可以使得结束宏后面的代码的警告再次出现。
    
     你也可以在 http://fuckingclangwarnings.com 找到这些警告列表
     */
    
    // 这个函数没有消除警告
    static void test1(void){
        id obj = [NSObject new];
        SEL aSEL = @selector(theSELName);
        if ([obj respondsToSelector:aSEL]) {
            [obj performSelector:aSEL];
        }
    }
    
    // 使用消除警告宏消除警告
    NO_WARNING_BEGIN(-Wunused-function)
    NO_WARNING_BEGIN(-Wundeclared-selector)
    NO_WARNING_BEGIN(-Warc-performSelector-leaks)
    
    // 不消除警告时,Xcode会在这一行显示警告:Unused function 'test2'
    static void test2(void){
        id obj = [NSObject new];
        // 不消除警告时,Xcode会在这一行显示警告:Undeclared selector 'theSELName'
        SEL aSEL = @selector(theSELName);
        if ([obj respondsToSelector:aSEL]) {
            // 不消除警告时,Xcode会在这一行显示警告:PerformSelector may cause a leak because its selector is unknown
            [obj performSelector:aSEL];
        }
    }
    NO_WARNING_END
    
    #endif
    
    #endif /* Warning_h */

    相关文章

      网友评论

        本文标题:新瓶装老酒,用宏来快速消除Xcode警告

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