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

当我们没有新需求时,就会手痒痒要消除项目中的警告,即不会太无聊,又不会让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 */
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容