在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的比较多,于是就考虑了一下这个问题:这两种类型有啥区别?

这里不得不吐槽一下<Objectice-C程序设计>这本书,当初就是看这本书了解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

[Objective-C] 从NSInteger说开去的更多相关文章

  1. 从Linux内核升级的必要性说开去

    Linux内核更新超级频繁,可是有必要时刻升级吗?个人感觉没有必要,可是你要时刻关注新特性列表,然后把自己的内核升级到离最新版本号差一两个月公布的版本号而不是最新版本号.以保证稳定性,由于一两个月的时 ...

  2. (转)2019年 React 新手学习指南 – 从 React 学习线路图说开去

    原文:https://www.html.cn/archives/10111 注:本文根据 React 开发者学习线路图(2018) 结构编写了很多新手如何学习 React 的建议.2019 年有标题党 ...

  3. 由SOAP说开去 - - 谈谈WebServices、RMI、RPC、SOA、REST、XML、JSON

    引子: 关于SOAP其实我一直模模糊糊不太理解,这种模模糊糊的感觉表述起来是这样: 在使用web服务时(功能接口),本来我就可以通过安卓中固有的http类(使用http协议),来发送http请求,并且 ...

  4. Java多线程总结之由synchronized说开去

    更新完毕,结贴,以后有新的想法再开新帖 这几天不断添加新内容,给个大概的提纲吧,方面朋友们阅读,各部分是用分割线隔开了的: synchronized与wait()/notify() JMM与synch ...

  5. 从谷歌 GFS 架构设计聊开去

    伟人说:“人多力量大.” 尼古拉斯赵四说:“没有什么事,是一顿饭解决不了的!!!如果有,那就两顿.” 研发说:“需求太多,人手不够.” 专家说:“人手不够,那就协调资源,攒人头.” 释义:一人拾柴火不 ...

  6. 从《BLAME!》说开去——新一代生产级卡通真实感混合的渲染方案

    <BLAME!>是Polygon Pictures Inc.(以下简称PPI)创业33周年以来制作的第一部CG剧场电影,故事来自于贰瓶勉的同名漫画作品(中文译名为<探索者>或者 ...

  7. 由底层和逻辑说开去——c++之类与对象的深入剖析

    类是什么,对象是什么,  这两个问题在各个c++书里面都以一种抽象的描述方式,给了我们近乎完美的答案,然后我好像就知道什么是类什么是对象了,但是当扪心自问,类在哪儿,对象在哪儿,成员方法在哪儿,成员变 ...

  8. 从一个Bug说开去--解决问题的思路,Linked Server, Bulk Insert, DataTable 作为参数传递

    声名— 部分内容为杜撰,如有雷同,不胜荣幸! 版权所有,如要引用,请标明出处! 如果打赏,请自便! 1       背景介绍 最近一周在忙一个SQL Server 的Bug,一个简单的Bug,更新两张 ...

  9. 从Excel转Access的一个方法说开去(DataRow的state状态)

    因为客户对access不太熟悉,更喜欢玩EXCEL.但是系统要求导入ACCESS.所以我们得做个把EXCEL转换成Access的小工具.(别问我为啥不让系统直接导入excel....我不知道!),然后 ...

随机推荐

  1. office2013安装与卸载

    一.office2013卸载不干净,重新安装的时候就会报错.下面是博主卸载的步骤: 第一步:下载office官方卸载工具 ,链接:http://pan.baidu.com/s/1nvuoEYd 密码: ...

  2. idea自己用得到的命令

    1.注释 Ctrl + / 单行注释 . 取消注释 Ctrl + Shift + / 多行注释 .取消注释 2.查找 Ctrl + N 通过输入类名打开类(标准说法是查找类文件) Ctrl + Shi ...

  3. C# 多线程八之并行Linq(ParallelEnumerable)

    1.简介 关于并行Linq,Ms官方叫做并行语言集成(PLINQ)查询,其实本质就是Linq的多线程版本,常规的Linq是单线程的,也就是同步的过程处理完所有的查询.如果你的Linq查询足够简单,而且 ...

  4. 编写自己的SpringBoot-starter

    前言 我们都知道可以使用SpringBoot快速的开发基于Spring框架的项目.由于围绕SpringBoot存在很多开箱即用的Starter依赖,使得我们在开发业务代码时能够非常方便的.不需要过多关 ...

  5. [java初探05]__数组的简单认识及Arrays类的常用方法

    数组是具有相同数据类型的一组数据的集合.在程序设计中,这样的集合称之为数组.数组的每个元素都具有相同的数据类型,在Java中数组也被看为一个对象. 在里,了解了数组的定义之后, 我们知道了,数组并不是 ...

  6. 【转】Java中堆和栈的区别

    Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new.newarray.anewarray和multianewarray等 指令建立,它们不需要程序代码来显式的释放.堆是由垃圾回收 ...

  7. Spring Security 之 Remember-Me (记住我)

    效果:在用户的session(会话)过期或者浏览器关闭后,应用程序仍能记住它.用户可选择是否被记住.(在登录界面选择)   “记住”是什么意思?     就是下次你再访问的时候,直接进入系统,而不需要 ...

  8. docker-部署elk-6.1.3

    1.更新daocker版本 2.pull官方的镜像 https://www.elastic.co/guide/en/elasticsearch/reference/6.1/docker.html ht ...

  9. oracle 删除服务sc delete Oracle

    oracle 删除服务sc delete OracleVssWriterorcl -----(oracle orcl vss writer service的服务名!)

  10. Re:从零开始的Spring Session(二)

    上一篇文章介绍了一些Session和Cookie的基础知识,这篇文章开始正式介绍Spring Session是如何对传统的Session进行改造的.官网这么介绍Spring Session: Spri ...