[Objective-C] 从NSInteger说开去

坏习惯的开端

初写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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏YoungGy

ML基石_8_NoiseAndError

recap Noise and Probabilistic Target noise来源 Probabilistic Target Error Measure ...

1935
来自专栏三木的博客

Kobject浅析

面向对象的思想的确在应用软件的开发中颇具优势,它让一个个纯逻辑的函数和数据变成了一个个有生命的个体。鉴于性能的考虑,系统软件的实现(例如linux kernel...

1958
来自专栏web编程技术分享

从啥也不会到可以胜任最基本的JavaWeb工作,推荐给新人的学习路线(二)

3265
来自专栏从流域到海域

《笨办法学python》 第14课手记

《笨办法学Python》 第14课手记 本节课将argv和raw_input和起来使用,作者在之前说,这个组合是个蛮顺手的用法。请注意,引入argv并使用arg...

23410
来自专栏牛客网

今日头条/字节跳动 一、二面凉经(后端开发工程师)

视频面,约的下午三点,时间到了准时开始面试。一面结束后想着已经挂了,没想到状态变成了等待二面,二面完没多久通知面试结束,不通过。

7562
来自专栏CSDN技术头条

关系型数据库是如何运作的(上)

一说到关系型数据库,我总感觉缺了点什么。如果你尝试透过“关系型数据库是如何运作的”的关键词句来进行搜索,其搜索结果是少量的而且内容是简短的。难道说是由于它已经太...

2138
来自专栏葡萄城控件技术团队

Visual Studio 2015速递(1)——C#6.0新特性怎么用

系列文章 Visual Studio 2015速递(1)——C#6.0新特性怎么用 Visual Studio 2015速递(2)——提升效率和质量(VS20...

1928
来自专栏瓜大三哥

matlab GUI基础4

高级文件I/O——语音文件 1.读取带有分隔符的文件 在matlab中,使用向导将外部的数据文件导入到matlab的工作空间中,然后就可以进行分析和处理了。如...

2515
来自专栏不二小段

【爬虫与反爬】记一次网址编码研究

相爱相杀的爬虫与反爬工程师啊……愿你们和谐相处。 前些日子写爬虫时遇到一个比较奇怪的编码,是构造目标网址的一个组成部分,我更倾向于说是编码而不是加密,虽然的确有...

3458
来自专栏极客慕白的成长之路

通俗理解数据库范式

数据库范式是数据库设计中必不可少的知识,没有对范式的理解,就无法设计出高效率、优雅的数据库。甚至设计出错误的数据库。而想要理解并掌握范式却并不是那么容易。教科...

2132

扫码关注云+社区

领取腾讯云代金券