關于iOS里的警告
iOS調試
前言
一個好的程序猿,會重視他寫的每一行代碼,看到警告會去思考為什么,會去盡量的消除警告,消除警告是代碼潔癖必不可少的一項。所以對于iOS開發者來說了解警告的類型,并開啟必要的警告是必須的。下面是Build Setting
里關于warning
的配置選項。
Apple LLVM 8.0 - Warning Policies
這是關于所有warning的策略,分為以下三個點:
禁止所有的Warnings
Inhibit All Warnings
表示是否禁止所有的Warnings,默認為NO。如果設置為YES,那你就不會得到任何警告提示了。
迂腐的Warnings
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
之外的所有警告都等于錯誤。Build Setting里的警告選項
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
我們上面有提到在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提供了我們自己加入警告或者暫時關閉警告的辦法。
加入警告
強制加入一個警告:
<pre class="prettyprint linenums prettyprinted" data-anchor-id="8ltr" style="padding: 9.5px; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 14px; color: rgb(51, 51, 51); border-radius: 4px; display: block; margin: 0px 0px 20px; line-height: 20px; word-break: break-all; overflow-wrap: break-word; white-space: pre-wrap; background: none 0px 0px repeat scroll rgba(102, 128, 153, 0.05); border: 0px solid rgba(0, 0, 0, 0.15); box-shadow: rgba(255, 255, 255, 0.1) 0px 1px 2px inset, rgba(102, 128, 153, 0.05) 45px 0px 0px inset, rgba(102, 128, 153, 0.05) 0px 1px 0px;">
//Generate a warning
#pragma message "Warning 1"
//Another way to generate a warning
#warning "Warning 2"
</pre>
兩種強制警告的方法在視覺效果上結果是一樣的,但是警告類型略有不同,一個是-W#pragma-messages
,另一個是-W#warnings
。對于第二種寫法,把warning換成error,可以強制使編譯失敗。比如在發布一些需要API Key之類的類庫時,可以使用這個方法來提示別的開發者別忘了輸入必要的信息。
<pre class="prettyprint linenums prettyprinted" data-anchor-id="egkd" style="padding: 9.5px; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 14px; color: rgb(51, 51, 51); border-radius: 4px; display: block; margin: 0px 0px 20px; line-height: 20px; word-break: break-all; overflow-wrap: break-word; white-space: pre-wrap; background: none 0px 0px repeat scroll rgba(102, 128, 153, 0.05); border: 0px solid rgba(0, 0, 0, 0.15); box-shadow: rgba(255, 255, 255, 0.1) 0px 1px 2px inset, rgba(102, 128, 153, 0.05) 45px 0px 0px inset, rgba(102, 128, 153, 0.05) 0px 1px 0px;">
//Generate an error to fail the build.
#error "Something wrong"
</pre>
關閉警告
全局關閉
在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的開關
相對文件打開警告也類似。-
在某幾行關閉某個警告
<pre class="prettyprint linenums prettyprinted" style="padding: 9.5px; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 14px; color: rgb(51, 51, 51); border-radius: 4px; display: block; margin: 0px 0px 20px; line-height: 20px; word-break: break-all; overflow-wrap: break-word; white-space: pre-wrap; background: none 0px 0px repeat scroll rgba(102, 128, 153, 0.05); border: 0px solid rgba(0, 0, 0, 0.15); box-shadow: rgba(255, 255, 255, 0.1) 0px 1px 2px inset, rgba(102, 128, 153, 0.05) 45px 0px 0px inset, rgba(102, 128, 153, 0.05) 0px 1px 0px;">
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable"
int a;
#pragma clang diagnostic pop
</pre>
這樣如果之后a未被使用,也不會出現
unused-variable
類型的警告了。
警告類型列表
這里我整理了一篇專門收集警告:iOS警告類型,以供參考。
相關問題
pod里的警告沒有提示
需要在Edit Scheme
->Build
里加入對應pod的target,才能顯示那個pod里的警告。
警告開啟建議
個人喜好(代碼潔癖)不同,會有不同的需求。我的建議是對于所有項目,特別是新開的項目,首先開啟-Wall
和-Wextra
,然后在此基礎上構建項目并且避免一切警告。如果在開發過程中遇到了某些確實無法解決或者確信自己的做法是正確的話(其實這種情況,你的做法一般即使不是錯誤的,也會是不那么正確的),可以有選擇性地關閉某些警告。一般來說,關閉的警告項目不應該超過一只手能數出來的數字,否則一定哪兒出問題了.
關閉的warning需要列出文檔以供開發人員參考,知道哪些warning關閉了。包括全局關閉、相應文件關閉、在某幾行關閉某個警告等。
參考
談談Objective-C的警告
清除Masonry中的警告