在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. 深入浅出SQL Server中的死锁(实战篇)

    简介 死锁的本质是一种僵持状态,是多个主体对于资源的争用而导致的.理解死锁首先需要对死锁所涉及的相关观念有一个理解. 一些基础知识 要理解SQL Server中的死锁,更好的方式是通过类比从更大的面理 ...

  2. Hadoop(三)搭建Hadoop全分布式集群

    原文地址:http://www.cnblogs.com/zhangyinhua/p/7652686.html 阅读目录(Content) 一.搭建Hadoop全分布式集群前提 1.1.网络 1.2.安 ...

  3. 全网最全的Windows下Anaconda2 / Anaconda3里正确下载安装用来向微信好友发送消息的itchat库(图文详解)

    不多说,直接上干货!  Anaconda2 里 PS C:\Anaconda2\Scripts> PS C:\Anaconda2\Scripts> pip.exe install itch ...

  4. Method 'initializationerror' not found.Opening the test classs JUnit4单元测试报错问题解决办法(图文详解)

    不多说,直接上干货! 问题现象 今天使用JUnit 4进行单元测试时,测试程序一直运行不起来,报method initializationerror not found错误,如下: 问题分析 网上说版 ...

  5. vue子组件传参给父组件

    关于父组件传参给子组件,可以看我另一篇文章 教程开始: 我们要实现的效果是:在子组件的Input框输入,父组件中实时更新显示.(也就是把子组件中的数据传给父组件) 一.子组件代码 template部分 ...

  6. MySql主从同步和延迟同步

    MySql同步与延迟同步 Mysql同步 一 Mysql主服务器上操作 1 开启服务器上的log_bin功能 # vim/etc/my.cnf 增加一下两行 log_bin=mysql-bin ser ...

  7. 【LeetCode题解】61_旋转链表(Rotate-List)

    目录 描述 解法:双指针 思路 Java 实现 Python 实现 复杂度分析 描述 给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: 1-> ...

  8. Solr 配置中文分词器 IK

    1. 下载或者编译 IK 分词器的 jar 包文件,然后放入 ...\apache-tomcat-8.5.16\webapps\solr\WEB-INF\lib\ 这个 lib 文件目录下: IK 分 ...

  9. MVC使用Flash来显示图片

    Insus.NET实现一些网站模版,如用户能动态变更网站的头,中间或是脚的部位,就是不太确定用户上传的是图片,还是Flash.因此想到一个较好的解决方法,就是使用Flash的组件去显示来源的图片或是. ...

  10. Oracle 图解安装

    1.找到安装exe打开. 2. 3. 4. 5. 6. 7. 8.