在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. spring 后处理器

    Bean后处理器 新建maven项目并添加spring依赖,目录结构如下 Axe public interface Axe { public String chop(); } Person publi ...

  2. SpringBoot入门 (十三) WebSocket使用

    本文记录在SpringBoot中使用WebSocket. 一 什么是WebSocket WebSocket是基于TCP协议的一种网络协议,它实现了浏览器与服务器全双工通信,支持客户端和服务端之间相互发 ...

  3. linux sticky

    文件的粘滞位(sticky)位是作什么用的? 普通文件的sticky位会被linux内核忽略, 目录的sticky位表示这个目录里的文件只能被owner和root删除 粘着位(Sticky bit) ...

  4. 调用web service出现“请求被中止: 请求已被取消。”

    在制作(www.helpqy.com)的后台时,使用StreamWrite向httpwebrequest.getrequeststream中写入Post数据后,一调用httpwebresponse.g ...

  5. 并发编程——ConcurrentHashMap#addCount() 分析

    前言 ConcurrentHashMap 精华代码很多,前面分析了 helpTransfer 和 transfer 和 putVal 方法,今天来分析一下 addCount 方法,该方法会在 putV ...

  6. 并发编程之 Thread 类过期方法和常用方法

    前言 在 Java 刚诞生时,Thread 类就已经有了很多方法,但这些方法由于一些原因(有一些明显的bug或者设计不合理)有些已经废弃了,但是他们的方法名却是非常的好,真的是浪费.我们在进行并发必编 ...

  7. Mac 自带的Apache php 狼神的

    开启服务:sudo /usr/sbin/apachectl start 停止服务:sudo /usr/sbin/apachectl stop 重启服务:sudo /usr/sbin/apachectl ...

  8. MYSQL查询优化(Ⅱ)

    本文列举出五个MySQL查询优化的方法,当然,优化的方法还有很多. 1.优化数据类型 MySQL中数据类型有多种,如果你是一名DBA,正在按照优化的原则对数据类型进行严格的检查,但开发人员可能会选择他 ...

  9. 基于hive的日志分析系统

    转自 http://www.cppblog.com/koson/archive/2010/07/19/120773.html           hive 简介         hive 是一个基于  ...

  10. Guava RateLimiter实现接口API限流

    一.简介 Guava提供的RateLimiter可以限制物理或逻辑资源的被访问速率.RateLimit二的原理类似与令牌桶,它主要由许可发出的速率来定义,如果没有额外的配置,许可证将按每秒许可证规定的 ...