斷言NSAssert的使用

来源:https://www.cnblogs.com/jiuyi/archive/2019/01/30/10337804.html
-Advertisement-
Play Games

1. NSAssert 斷言(NSAssert)是一個巨集,在開發過程中使用NSAssert可以及時發現程式中的問題。 NSAssert聲明如下: #define NSAssert(condition, desc, ...) condition:條件表達式。條件成立時,運行後面程式;不成立時,拋出帶有 ...


1. NSAssert

斷言(NSAssert)是一個巨集,在開發過程中使用NSAssert可以及時發現程式中的問題。

NSAssert聲明如下:

#define NSAssert(condition, desc, ...)
  • condition:條件表達式。條件成立時,運行後面程式;不成立時,拋出帶有desc描述的異常信息。
  • desc:異常描述,通常為NSString類型對象。用於描述條件表達式不成立的錯誤信息和參數的占位符。
  • ...:desc字元串中的參數。

假設我們需要判斷變數值是否大於5,我們可以用如下代碼進行判斷。

int i = 6;
NSAssert(i>5, @"i must bigger than 5");

運行後,控制台沒有任何輸出。

把變數i的值改為2,如下所示:

int i = 2;
NSAssert(i>5, @"i must bigger than 5");

運行demo,demo會崩潰。在控制台輸出如下信息:

*** Assertion failure in -[ViewController viewDidLoad], /Users/ad/Library/Mobile Documents/com~apple~CloudDocs/file2016/NSAssert0709/NSAssert0709/ViewController.m:23
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'i must bigger than 5'

通過控制台輸出的信息,可以得到崩潰發生於:ViewController類的viewDidLoad 方法中,該文件位於/Users/ad/Library/Mobile Documents/comappleCloudDocs/file2016/NSAssert0709/NSAssert0709/ViewController.m,導致崩潰的代碼位於第23行,崩潰原因為:i must bigger than 5。

使用NSAssert時可以對輸出信息進行傳值。

int i = 2;
NSAssert1(i>5, @"The real value is %i", i);

輸出為:

*** Assertion failure in -[ViewController viewDidLoad], /Users/ad/Library/Mobile Documents/com~apple~CloudDocs/file2016/NSAssert0709/NSAssert0709/ViewController.m:23
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'The real value is 2'

NSAssert 用於Objective-C,NSCAssert用於C語言中。

NSAssert1 desc帶有一個參數,NSAssert2 的 desc 帶有兩個參數,……,NSAssert5 帶有五個參數。斷言可以帶有零至五個參數。

 

也許你會好奇為什麼desc中不使用[NSString stringWithFormat:...]格式,而要有五個NSAssert?因為NSAssert()的實現就是一個巨集,因此,要處理異常信息中不同數量參數,就要有多個巨集,所以就有了

NSAssert(condition, dest)NSAssert1(condition, formatDest, arg1)NSAssert2(condition, formatDest, arg1, arg2)...NSAssert5(...)

NSAssertNSLog都可以在控制台輸出,但NSAssert輸出後程式立即 crash,控制台也會輸出程式遇到錯誤的位置等信息,而NSLog只用於輸出信息。

2. NSParameterAssert

如果需要判斷傳入參數是否符合要求,可以使用NSParameterAssert

- (NSString *)processItem:(NSUInteger)index {
    NSParameterAssert(index<self.myArray.count);
    // do something else
}

如果傳入參數index大於myArray數組內元素數量,則程式會崩潰。控制它輸出如下:

*** Assertion failure in -[ViewController processItem:], /Users/ad/Library/Mobile Documents/com~apple~CloudDocs/file2016/NSAssert0709/NSAssert0709/ViewController.m:31
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: index<self.myArray.count'

崩潰信息中會告訴你哪一行代碼出錯了,崩潰原因是什麼。

NSParameterAssert用於Objective-C,NSCParameterAssert用於C語言中。

3. 斷言預設只存在於debug版

從Xcode 4.2開始,release 版預設關閉了斷言。也就是當編譯發佈版時,任何調用NSAssert的地方都被空行替換。所以,不要在NSAssert內執行任何有效操作。

如果想要在發佈版中使用NSAssert,可以在 Build Setting 中的 Enable Foundation Assertions 中修改。

   

4. NSError

NSError 應該用在不是編程錯誤所產生的error,如文件未找到一類非致命性錯誤。你可以把錯誤信息發送給調用者,調用者會進行處理並繼續執行,也可以用警報控制器展現給用戶。

總結

對來源於系統內部的可靠數據使用斷言,即用斷言來處理絕不應該發生的情況。不要對外部不可靠數據(如用戶輸入、文件、網路讀取等)使用斷言,即對於外部不可靠數據或預期會發生的情況應當使用錯誤處理。同時要避免把需要執行的代碼放到斷言中,斷言可以看成可執行的註釋。

來源於系統外部的數據都是不可信的,需要嚴格檢查(通常是錯誤處理)才能放行到系統內部,這相當於一個守衛。而對於系統內部的交互(如調用其他方法),如果每次也都要去處理輸入的數據,也就相當於系統沒有可信的邊界,會讓代碼變的臃腫。事實上,在系統內部傳遞給方法正確的參數是調用者的責任,調用者應該確保傳遞給所調用方法的數據是符合要求的。這樣就隔離了不可靠的外部環境和可靠的內部環境,降低複雜度。

但在開發階段,代碼極可能存在缺陷,有可能是處理外部數據的邏輯不周全或調用內部方法的代碼存在錯誤,最終造成調用失敗。這個時候,斷言就可以發揮作用,用來確診到底哪一部分問題導致程式出錯。在清理了所有缺陷後,內外有別的信用體系就建立起來了。等到發行版的時候,這些斷言就沒有存在的必要了。

單元測試可能是一個更好的方法,但有些情況下(如複雜的演算法過程中),我們希望在代碼中執行檢查,這時斷言將更有效。

參考資料:

  1. What is NSAssert1?
  2. Objective-C: Assertion vs. Exception vs. Error
  3. iOS開發中斷言的使用—NSAssert()

作者:pro648

 


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

-Advertisement-
Play Games
更多相關文章
  • 參考文章: "約束佈局ConstraintLayout看這一篇就夠了" "ConstraintLayout 屬性篇" 介紹 Android 是谷歌推出替代 的組件。 支持相對佈局、線性佈局、幀佈局,看來更像是 、 t、`RelativeLayout·三者的結合體,並且比這三者更強大的是實現了百分比布 ...
  • 一、UIScrollView是什麼? 1、UIScrollView是滾動的view,UIView本身不能滾動,子類UIScrollview拓展了滾動方面的功能。 2、UIScrollView是所有滾動視圖的基類。以後的UITableView,UITextView等視圖都是繼承於該類。 使用場景:顯示 ...
  • 最近在項目中用到了手勢操作,鍵盤迴收時還是挺常用的,現在總結下,多謝網路上大神們的分享。 先分享下我在項目中用的代碼: 將相應代碼複製到你的工程中即可使用,由於代碼中已經有詳細的解釋說明,這裡就不在重覆解釋了。 代碼中只是列舉了單指與雙指對於單擊或多擊的處理,同理多指的操作需修改numberOfTo ...
  • 一、創建過程 二、TextView點擊事件 對比Java代碼,雖然代碼相似,可以看出Kotlin簡潔: 大大減少樣板代碼的數量。 三、kotlin知識點 😀Kotlin 程式文件以 .kt 結尾,如:hello.kt 、MainActivity.kt。 😀Android Studio 從 3.0 ...
  • 1.、首先,Controller需要實現兩個 delegate ,分別是 UITableViewDelegate 和 UITableViewDataSource2、然後 UITableView對象的 delegate要設置為 self。3、 然後就可以實現這些delegate的一些方法拉。 (1)- ...
  • 環境要求 1、運行環境 armeabi-v7a 2、系統要求 Android 5.0 (API Level 21)及以上 3、開發環境 Android Studio 下載地址:https://github.com/ArcsoftEscErd/ArcfaceDemo_Android SDK獲取地址請戳 ...
  • 轉載請標明出處,維權必究:https://www.cnblogs.com/tangZH/p/10338377.html 有時候APP需要獲取某些許可權,要讓用戶手動打開,那麼問題來了,若是直接提醒用戶出去找許可權入口,然後自己打開,用戶不一定找得到,因為現在的Android廠家定製的room五花八門,那 ...
  • 最近有關摺疊屏產品的新聞層出不窮,各家手機廠商也分別慢慢地亮出了自家的產品。然而市場上的一些APP仍然沒有很好地適配這樣的設備,顯示不正常和應用重啟的狀況時有發生。因此,我會用接下來的幾篇文章來點出有關摺疊屏開發中的一些需要註意的地方。 今天我們先來說一下 生命周期 ,這是廣大開發者特別需要註意的一 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...