談談Objective-C的警告 (轉)

来源:http://www.cnblogs.com/shouce/archive/2016/03/14/5274509.html
-Advertisement-
Play Games

原文地址:http://onevcat.com/2013/05/talk-about-warning/   一個有節操的程式員會在乎自己的代碼的警告,就像在乎飯碗邊上有隻死蟑螂那樣。 ——@onevcat 現在編譯器有時候會很吵,而編譯器給出的警告對開發者來說是很有用的信息。警告不會阻止繼續編譯和鏈


原文地址:http://onevcat.com/2013/05/talk-about-warning/

 

一個有節操的程式員會在乎自己的代碼的警告,就像在乎飯碗邊上有隻死蟑螂那樣。 ——@onevcat

重視編譯警告

現在編譯器有時候會很吵,而編譯器給出的警告對開發者來說是很有用的信息。警告不會阻止繼續編譯和鏈接,也不會導致程式不能運行,但是很多時候編譯器會先你一步發現問題所在,對於Objective-C來說特別如此。Clang不僅對於明顯的錯誤能夠提出警告(比如某方法或者介面未實現),也能對很多潛在可能的問題做出提示(比如方法已經廢棄或者有問題的轉換),而這些問題在很多時候都可能成為潛在的致命錯誤,必須加以重視。

像Ruby或者PHP這樣的動態語言沒有所謂的編譯警告,而C#或者Java這類語言的警告很多都是不得不照顧的廢棄方法什麼的,很多開發者已經習慣於忽略警告進行開發。OC由於現在由蘋果負責維護,Clang的LLVM也同時是蘋果在做,可以說從語言到編譯器到SDK全局都在掌握之中,因此做OC開發時的警告往往比其他語言的警告更有參考價值。打開儘可能多的警告提示,並且在程式開發中儘量避免生成警告,對於構建一個健壯高效的程式來說,是必須的。

在Xcode中開啟額外警告提示

Xcode的工程模板已經為我們設置開啟了一些預設和常用的警告提示,這些預設設置為了相容一些上年頭的項目,並沒有打開很多,僅是指對最危險和最常見的部分進行了警告。這對於一個新項目來說這是不夠用的(至少對我來說是不夠用的),在無數前輩大牛的教導下,首先要做的事情就是打開儘可能多的警告提示。

最簡單的方法是通過UI來打開警告。在Xcode中,Build Setting選項里為我們預留了一些打開警告的開關,找到並直接勾選相應的選項就可以打開警告。大部分時間里選項本身已經足夠能描述警告的作用和產生警告的時機,如果不是很明白的話,在右側的Quick Help面板里有更詳細的說明。對於OC開發來說特有的警告都在Apple LLVM compiler 4.2 - Warnings - Objective C一欄中,不管您是不是決定打開它們,都是值得花時間看一看加以瞭解的,因為它們都是寫OC程式時最應該避免的情況。另外幾個Apple LLVM compiler 4.2 - Warnings - …(All languages和C++)也包含了大量的選項,以方便控制警告產生。

Xcode設置中的警告選項

當然在UI里一個一個點擊激活警告雖然簡單,但每次都這樣來一回是一種一點也不有趣的做法,特別是在你已經瞭解它們的內容並決定打開它們的時候。在編譯選項中加入合適的flag能夠打開或者關閉警告:在Build Setting中的Other C Flags里添加形似-W...的編譯標識。你可以在其中填寫任意多的-W...以開關某些警告,比如,填寫為-Wall -Wno-unused-variable即可打開“全部”警告(其實並不是全部,只是一大部分嚴重警告而已),但是不啟用“未使用變數”的警告。使用-W...的形式,而不是在UI上勾選的一大好處是,在編譯器版本更新時,新加入的警告如果包含在-Wall中的話,不需要對工程做任何修改,新的警告即可以生效。這樣立即可以察覺到同一個工程由於編譯器版本更新時可能帶來的隱患。另外一個更重要的原因是..Xcode的UI並沒有提供所有的警告 =_=||..

剛纔提到的,需要註意的是,-Wall的名字雖然是all,但是這真的只是一個迷惑人的詞語,實際上-Wall涵蓋的僅只是所有警告中的一個子集。在StackExchange上有一個在Google工作的Clang開發者進行的回答,其中解釋了有一些重要的警告組:

  • -Wall 並不是所有警告。這一個警告組開啟的是編譯器開發者對於“你所寫的代碼中有問題”這一命題有著很高的自信的那些警告。要是在這一組設定下你的代碼出現了警告,那基本上就是你的代碼真的存在嚴重問題了。但是同時,並不是說打開Wall就萬事大吉了,因為Wall所針對的僅僅只是經典代碼庫中的為數不多的問題,因此有一些致命的警告並不能被其捕捉到。但是不論如何,因為Wall的警告提供的都是可信度和優先順序很高的警告,所以為所有項目(至少是所有新項目)打開這組警告,應該成為一種良好的習慣。
  • -Wextra 如其所名,-Wextra組提供“額外的”警告。這個組和-Wall組幾乎一樣有用,但是有些情況下對於代碼相對過於嚴苛。一個很常見的例子是,-Wextra中包含了-Wsign-compare,這個警告標識會開啟比較時候對signed和unsigned的類型檢查,當比較符兩邊一邊是signed一邊是unsigned時,產生警告。其實很多代碼並沒有特別在意這樣的比較,而且絕大多數時候,比較signed和unsigned也是沒有太大問題的(當然不排除會有致命錯誤出現的情況)。需要註意,-Wextra-Wall是相互獨立的兩個警告組,雖然裡面打開的警告標識有個別是重覆的,但是兩組並沒有包含的關係。想要同時使用的話必須在Other C Flags中都加上
  • -Weverything 這個是真正的所有警告。但是一般開發者不會選擇使用這個標識,因為它包含了那些還正在開發中的可能尚存bug的警告提示。這個標識一般是編譯器開發者用來調試時使用的,如果你想在自己的項目里開啟的話,警告一定會爆棚導致你想開始撞牆..

-Wall和-Wextra下0警告的工程,在-Weverything下的表現,可以用慘不忍睹來形容

關於某個組開啟了哪些警告的說明,在GCC的手冊中有一個參考。雖然蘋果現在用的都是LLVM了,但是這部分內容應該是繼承了GCC的設定。

控制警告,局部加入或關閉

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"

對於關閉某個警告,如果需要全局關閉的話,直接在Other C Flags里寫-Wno-...就行了,比如-Wextra -Wno-sign-compare就是一個常見的組合。如果相對某幾個文件開啟或禁用警告,在Build Phases的Compile Source相應的文件中加入對應的編譯標識即可。如果只是想在某幾行關閉某個警告的話,可以通過臨時改變診斷編譯標記來抑制指定類型的警告,具體如下:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable"

int a;

#pragma clang diagnostic pop

如果a之後沒有被使用,也不會出未使用變數的警告了。對於想要抑制的警告類型的標識名,可以在build產生該警告後的build log中看到。Xcode中的話,快捷鍵Cmd+7然後點擊最近的build log中,進入詳細信息中就能看到了。

警告的詳細信息,可以找到標識符

我應該開啟哪些警告提示

個人喜好(代碼潔癖)不同,會有不同的需求。我的建議是對於所有項目,特別是新開的項目,首先開啟-Wall-Wextra,然後在此基礎上構建項目並且避免一切警告。如果在開發過程中遇到了某些確實無法解決或者確信自己的做法是正確的話(其實這種情況,你的做法一般即使不是錯誤的,也會是不那麼正確的),可以有選擇性地關閉某些警告。一般來說,關閉的警告項目不應該超過一隻手能數出來的數字,否則一定哪兒出問題了..

是否要讓警告等於錯誤

一種很常見的做法和代碼潔癖是將警告標識為錯誤,從而中斷編譯過程。這讓開發者不得不去修複這些警告,從而保持代碼乾凈整潔。在Xcode中,可以通過勾選相應的Treat Warnings as Errors來開啟,或者加入-Werror標識。我個人來說不喜歡使用這個設定,因為它總是打斷開發流程。很多時候並不可能把代碼全寫完再編譯調試,相反地,我更喜歡寫一點就編譯運行一下看看結果,這樣在中間debug編譯的時候會出現警告也不足為奇。另外,如果做TDD開發時,也可能會有大量正常的警告出現,如果有警告就不讓編譯的話,開發效率可能會打折扣。一個比較好的做法是只在Release Build時將警告視為錯誤,因為Xcode中是可以為Debug和Release分別指定標識的,所以這很容易做到。

另外也可以只把某些警告當作錯誤,-Werror=...即可,同樣地,也可以在-Werror被激活時使用-Wno-error=...來使某些警告不成為錯誤。結合使用這些編譯標識可以達到很好的控制。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我不喜歡一開始就去討論某某有多強大,因為我覺得那樣沒意思,首先我們的知道它是乾什麼,對我們有啥用,再去討論它的強大之處也不遲。那和往常一樣我們先來看幾個例子。 又比如我們想提取var str = 'eignwererherhtml5ewrqrpasfnh' ;這段文本裡面的html5,又應該怎麼做,
  • [1]line-height [2]vertical-align [3]應用
  • <!DOCTYPE> 聲明不是 HTML 標簽;它是指示 web 瀏覽器關於頁面使用哪個 HTML 版本進行編寫的指令。 在 HTML 4.01 中,<!DOCTYPE> 聲明引用 DTD,因為 HTML 4.01 基於 SGML。DTD 規定了標記語言的規則,這樣瀏覽器才能正確地呈現內容。 HTM
  • /* 01 HTTP請求 */ 重點:1.超文本傳輸協議. 2.http請求過程. {     1> http協議: 超文本傳輸協議(Hypertext Transfer Protocol)     {         http協議規定了客戶端和伺服器之間的數據傳輸格式.           
  • HTML元素的ID和Name屬性的區別今天突然興緻來了,想深究下這兩屬性的具體區別最classical的答案:ID就像是一個人的身份證號碼,而Name就像是他的名字,ID顯然是唯一的,而Name是可以重覆的。      顯然這個ID和Name的解答說的太籠統了,當然那個解釋對於ID來說是完全對的,它
  • Some Structure About CSS Layout Position,Layer[層次] Box Model Visual Formatting Model BFC[block formatting content],IFC[inline formatting content] Styl...
  • 仍記得剛來到公司的時候,老大跟我們說起原型鏈、閉包、MV*之類的東西,當時真的是一臉懵逼的樣子啊哈哈 在公司做前端開發也差不多四個月了,每一天感覺都是很忙碌,都是忙著寫業務代碼或者自己在學習新東西,總感覺很多知識點在這樣的狀態下,匆匆忙忙就略過了,自己並沒有真正理解掌握下來,還是要趁有時間還是把那些
  • jquery通過ajax方法獲取json數據不執行success回調方法
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...