当我们没有新需求时,就会手痒痒要消除项目中的警告,即不会太无聊,又不会让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 */