@qidiandasheng
        
        2022-08-23T01:30:23.000000Z
        字数 3712
        阅读 5682
    iOS调试&工具
一个好的程序猿,会重视他写的每一行代码,看到警告会去思考为什么,会去尽量的消除警告,消除警告是代码洁癖必不可少的一项。所以对于iOS开发者来说了解警告的类型,并开启必要的警告是必须的。下面是Build Setting里关于warning的配置选项。
这是关于所有warning的策略,分为以下三个点:
Inhibit All Warnings表示是否禁止所有的Warnings,默认为NO。如果设置为YES,那你就不会得到任何警告提示了。
Pedantic Warnings这个主要跟C和C++的标准有关,Pedantic意思是迂腐的,也就是说那些没有严格按照ISO C和ISO C++标准的代码是否显示。默认为NO,也就是不提示。
Treat Warnings as Errors,一种很常见的做法和代码洁癖是将警告标识为错误,从而中断编译过程。这让开发者不得不去修复这些警告,从而保持代码干净整洁。这个选项默认是NO,设置为YES,就会将警告等于错误。有时候我们在开发时不想被一些简单的warning给打断,那么可以先设置Debug为NO,Release为YES,在build release时就可以发现这些warning了。
我们也可以在Other C Flags里加入-Werror标识将警告等于错误。
如果要将某一类警告等于错误可以这样写-Werror=...。示例如下:
![]()
设置-Werror=unused-function之后表示只有unused-function警告等于错误。
也可以在-Werror被激活时使用-Wno-error=...来使某些警告不成为错误。示例如下:
![]()
设置-Werror和-Wno-error=unused-function之后表示除unused-function之外的所有警告都等于错误。
Xcode的工程模板已经为我们设置开启了一些默认和常用的警告提示,但是这些警告有时候是不够的,你需要开启更多的警告类型来找到你代码中不合理的地方。
主要分为以下几大块: 
Apple LLVM 8.0 - Warning - All languages、 
Apple LLVM 8.0 - Warning - C++、 
Apple LLVM 8.0 - Warning - Objective C、 
Apple LLVM 8.0 - Warning - Objective C and ARC。
在上面这些大块下面都有对应warning的配置选项。如下图是跟All languages相关的一些warning,我们能看到之前例子里的两种类型的warning设置为YES,表示这两种类型的warning是提示的。
我们上面有提到在Other C Flags中加入-Werror、-Wno-error=...、-Werror=...,来实现类似于Treat Warnings as Errors选项的效果及更强大的扩展。
其实我们也可以在Other C Flags加入特别的标识来达到Build Setting里设置对应警告选项BOOL值的效果。
Other C Flags里设置的优先级是大于某一个具体配置的。如在Apple LLVM 8.0 - Warning - All languages中的选项Unused Variable设置为YES,那么就表示这种类型的warning是会提示的。但是我在Other C Flags中加入-Wno-unused-variable,表示这种类型的warning是不提示的。 
那么最后以Other C Flags中的设置为准,也就是不会提示这种类型的warning。
Other C Flags中具有以下几种标记类型:
这部分上面已经提到过,包括-Werror、-Wno-error=...、-Werror=...。
-W...开启某些警告,如-Wunused-variable。-Wno-...关闭某些警告,如-Wno-unused-variable。
-Wall 并不是所有警告。这一个警告组开启的是编译器开发者对于“你所写的代码中有问题”这一命题有着很高的自信的那些警告。要是在这一组设定下你的代码出现了警告,那基本上就是你的代码真的存在严重问题了。但是同时,并不是说打开Wall就万事大吉了,因为Wall所针对的仅仅只是经典代码库中的为数不多的问题,因此有一些致命的警告并不能被其捕捉到。但是不论如何,因为Wall的警告提供的都是可信度和优先级很高的警告,所以为所有项目(至少是所有新项目)打开这组警告,应该成为一种良好的习惯。
-Wextra 如其所名,-Wextra组提供“额外的”警告。这个组和-Wall组几乎一样有用,但是有些情况下对于代码相对过于严苛。一个很常见的例子是,-Wextra中包含了-Wsign-compare,这个警告标识会开启比较时候对signed和unsigned的类型检查,当比较符两边一边是signed一边是unsigned时,产生警告。其实很多代码并没有特别在意这样的比较,而且绝大多数时候,比较signed和unsigned也是没有太大问题的(当然不排除会有致命错误出现的情况)。需要注意,-Wextra和-Wall是相互独立的两个警告组,虽然里面打开的警告标识有个别是重复的,但是两组并没有包含的关系。想要同时使用的话必须在Other C Flags中都加上。
-Weverything 这个是真正的所有警告。但是一般开发者不会选择使用这个标识,因为它包含了那些还正在开发中的可能尚存bug的警告提示。这个标识一般是编译器开发者用来调试时使用的,如果你想在自己的项目里开启的话,警告一定会爆棚导致你想开始撞墙。
如果知道对应类型的warning的标识名是什么?
可以先查看左侧的warning提示,如下图中就是unused-variable和unused-function两种警告的标识。
或者查看GCC的手册,里面会列出很多标识,基本上跟warning提示对比下应该就能找出来了。
Clang提供了我们自己加入警告或者暂时关闭警告的办法。
强制加入一个警告:
//Generate a warning#pragma message "Warning 1"//Another way to generate a warning#warning "Warning 2"
两种强制警告的方法在视觉效果上结果是一样的,但是警告类型略有不同,一个是-W#pragma-messages,另一个是-W#warnings。对于第二种写法,把warning换成error,可以强制使编译失败。比如在发布一些需要API Key之类的类库时,可以使用这个方法来提示别的开发者别忘了输入必要的信息。
//Generate an error to fail the build.#error "Something wrong"
全局关闭 
在build setting里找到对应的警告选项设置为NO即可。或者在build setting中的Other C Flags里加入-Wno-...标识。
相应文件关闭 
在Build Phases的Compile Source相应的文件中的Compiler Flags加入对应的编译标识即可,如-Wno-unused-variable。优先级如下: 
Build Phases的Compile Source>Build Setting的Other C Flags>Build Setting中的某一中具体warning的开关 
相对文件打开警告也类似。
在某几行关闭某个警告
#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wunused-variable"int a;#pragma clang diagnostic pop
这样如果之后a未被使用,也不会出现unused-variable类型的警告了。
这里我整理了一篇专门收集警告:iOS警告类型,以供参考。
需要在Edit Scheme->Build里加入对应pod的target,才能显示那个pod里的警告。
个人喜好(代码洁癖)不同,会有不同的需求。我的建议是对于所有项目,特别是新开的项目,首先开启-Wall和-Wextra,然后在此基础上构建项目并且避免一切警告。如果在开发过程中遇到了某些确实无法解决或者确信自己的做法是正确的话(其实这种情况,你的做法一般即使不是错误的,也会是不那么正确的),可以有选择性地关闭某些警告。一般来说,关闭的警告项目不应该超过一只手能数出来的数字,否则一定哪儿出问题了.
关闭的warning需要列出文档以供开发人员参考,知道哪些warning关闭了。包括全局关闭、相应文件关闭、在某几行关闭某个警告等。