[Objective-C] 從NSInteger說開去

来源:http://www.cnblogs.com/rossoneri/archive/2016/02/28/5223969.html
-Advertisement-
Play Games

在iOS開發過程中,我一直習慣於使用C語法里的基本類型,而很少用(除非必須使用)Foundation的數據類型。最近看了一些資料,發現自己這樣寫可能有風險,雖然目前沒遇到過相關的問題,但這是非常需要註意的一點。 新博客 "wossoneri.com" 壞習慣的開端 初寫iOS時,我做的是把原項目從


在iOS開發過程中,我一直習慣於使用C語法里的基本類型,而很少用(除非必須使用)Foundation的數據類型。最近看了一些資料,發現自己這樣寫可能有風險,雖然目前沒遇到過相關的問題,但這是非常需要註意的一點。

新博客wossoneri.com

壞習慣的開端

初寫iOS時,我做的是把原項目從Android端移植到iOS端。因為涉及到不同語言,又因為不熟悉iOS,加上還要與用C寫的網路庫進行糾纏,我小心翼翼的用了基本數據類型完成大多數編碼。能用int就堅決不用NSInteger,能用float就堅決不用CGFloat。你可能會問,雖然這個過程用到的語言很雜,寫Objective-C的時候就大膽的用Foundation的數據類型唄。想法很好,只是當時我看不懂我們網路庫實現原因不敢亂改代碼,怕傷著哪個地方的邏輯,最後代碼移著移著,我的.m文件就變成了.mm文件——對,變成Objective-CC++混編代碼了。當時就索性一股腦的用C語言的基本數據類型去做了。現在想想我入門iOS的過程真是坎坷呢,留下了一堆爛毛病。

不過好在我現在開始拼命的多看資料,一點點把走的彎路走回來。

一次突然的疑問

平時也會看Github上面的一些代碼,發現代碼里用到int的比較少,用NSInteger的比較多,於是就考慮了一下這個問題:這兩種類型有啥區別?

這裡不得不吐槽一下這本書,當初就是看這本書瞭解O-C語法的,可書上的介紹與代碼全是int的,完全沒見NSInteger的影子。可見學習這事不能只靠一本書,畢竟書的內容覆蓋面有限。

關於NSInteger和int的優劣

從查看頭文件可以看到其實這樣定義的:

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

這段定義是說如果程式是在64位系統下運行的,NSInteger就代表long,如果是32位的就代表int
也就是說,如果你不知道程式將要在什麼系統環境下運行時,最好使用NSInteger,這樣可以保證數據很大時不出現問題。簡而言之,就是如果你並不考慮位數對程式的影響或者說你覺得並不能游刃有餘的操作intlong,那麼NSInteger是一個很安全的選擇。

那麼是不是說有了NSInteger就可以不用int了呢?

當然不,以上的前提都是基於一個很大範圍數字變數所要考慮的。當你的變數值的範圍在一個你可控的範圍內,使用int反而更合適,比如說,你要保存一張手機照片的尺寸,那麼幾千的值是絕對夠了的,於是用int也不會產生任何問題,而用NSInteger反而增加代碼閱讀難度。畢竟int作為通用的基本類型很直觀,相反的是NSInteger的代碼往其他地方移植也會對別人產生困擾(是不是想太多了: D),而且,從效率上來講,直接用int的效率還是略微要高一些的。

什麼時候用NSInteger

其實在Apple的文檔或者示例代碼里,intNSInteger都會存在,大多數出現NSInteger是在函數的返回值上。因為函數的返回值是根據參數而不斷變化的,範圍是不可控的,所以就會使用NSInteger作為返回值。

所以,簡單說來,凡是API用到了NSInteger,那就別用int了。一般情況代碼計數不會出現很大的值,畢竟32位的int範圍可達到-2147483648~2147483647。

然後說開去,說什麼

NSInteger類似,Foundation數據類型里也有類似於與float對應的CGFloat

/* Definition of `CGFLOAT_TYPE', `CGFLOAT_IS_DOUBLE', `CGFLOAT_MIN', and
   `CGFLOAT_MAX'. */

#if defined(__LP64__) && __LP64__
# define CGFLOAT_TYPE double
# define CGFLOAT_IS_DOUBLE 1
# define CGFLOAT_MIN DBL_MIN
# define CGFLOAT_MAX DBL_MAX
#else
# define CGFLOAT_TYPE float
# define CGFLOAT_IS_DOUBLE 0
# define CGFLOAT_MIN FLT_MIN
# define CGFLOAT_MAX FLT_MAX
#endif

/* Definition of the `CGFloat' type and `CGFLOAT_DEFINED'. */

typedef CGFLOAT_TYPE CGFloat;
#define CGFLOAT_DEFINED 1

看完定義就明白,CGFloat也是對於不同位的系統的容錯。
最後至於NSStringstd::string那區別就沒那麼簡單了。
對於常用的數據類型,就這些了。

對於這些數據類型的格式化,可以參考這部分文檔:formatSpecifiers

你覺得我這就說完了

起初遇到這個問題時,我就簡單的上網查了一下,感覺沒什麼區別。不過最近看博客,發現有個大神這樣講

應避免使用基本類型,建議使用 Foundation 數據類型

當時我就一驚,我的代碼用的都是int,壓根就沒打算用NSInteger,我突然覺得自己養成了一個很差的編碼習慣,而且我的代碼可能會對我以後求職有影響。

驚詐之餘我就上網找起資料,認真閱讀不同人的不同說法,然後得到一個我自己的結論:寫int並無大礙,而且用基本數據類型並沒什麼明顯缺陷,畢竟我也是知道什麼時候用int啊,long啊,'float'啊這些的。虛驚一場。

但這事還是有教訓的,那就是瞭解一個新東西一定要多瞭解一些,像我當初就對這個問題不以為意,突然提起來了心就虛了。
另外有一個收穫就是多看別人寫的博客多關註一些細微的知識點總是能學到新東西的。像今天這個問題一樣,對我已經寫好的代碼影響雖然不大,但我再寫這塊代碼時的確是更安心了對吧。

reference
When to use NSInteger vs. int


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

-Advertisement-
Play Games
更多相關文章
  • 使用view畫圖,有兩個重要的組件需要介紹: (1)Paint 可以理解為畫刷或者畫筆,去主要用來設置繪圖使用的顏色、填充方式、透明度、字體以及字體樣式等。 (2)Canvas 畫布,在view上顯示的圖形都是由canvas來繪製的,可以繪製矩形、圓、橢圓、扇形……。 Paint常見方法與屬性: (
  • 很多天之前就安裝了visual studio community 2015,今天閑著麽事想試一下Apache Cordova,用它來開發跨平臺App。在這之前需要配置N多東西,這裡找到了一篇MS官方文章:配置 Visual Studio Tools for Apache Cordova。看著這片文章
  • http://pan.baidu.com/share/link?shareid=3506499606&uk=4278629985&app=zd
  • RecyclerView是加強版的ListView,用於在有限的視窗中展示大量的數據,而LoadMoreRecyclerView則是為RecyclerView增加了載入更多的功能,先來看效果: 三種載入方式: 自動載入: 手動載入: 使用圖片動畫載入: 項目簡介: demo中的下拉刷新採用的是Swi
  • AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.y
  • AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.y
  • 本文簡單介紹了Android(Linux)串口驅動線路規程的使用。
  • 分類:C#、Android、VS2015; 創建日期:2016-02-28 一、簡介 廣播(Broadcast):其功能類似於收音機的廣播,你只要調到那個台(只要在接收的類中註冊了要接收的廣播),就能收到這個台播放的信息。 通知(Notifications):安卓的服務組件(Android Serv
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...