NSObject和id的区别以及Instancetype、id<NSObject>

我们来分析下这三种定义的各自含义和区别 以及最后说到id返回类型都写成Instancetype的好处:

  1. id foo1;
  2. NSObject *foo2;
  3. id <NSObject> foo3;

(1) id类型被称之为 万能指针,也就是可以指向任何对象,可以用于任何类型的对象。

它可以指向的类型不仅限于NSObject

id 我们经常看到运用的地方莫过于

@property (nonatomic, weak, nullable) id delegate;

这个是系统UIKit框架里uitableview定义的 delegate 用的是id的类型.(delegate委托是一种设计模式,是一种设计思想。委托经常依赖协议来实现)

因为我们通常设计一个类的delegate时候,没有办法确定是什么对象来做delegate,所以用id,表示任何对象都可以,这种不能确定类型的需求还是蛮多的,比如有的数组内容类型不一样,进行遍历的时候等。

这里也就体现了动态类型id.可以在代码运行时判断对象的类型。

使用id类型(又称强类型)可以在运行的时候使用任何数据类型来替换。动态类型让程序更加灵活,但会使数据的统一性降低。我们常用的静态类型如NSString等是有着自己的优势的,使用静态类型编译器可以完全分析代码的性能,可预知性更高。

编译器看到id以后,认为是动态类型,不在检查类型

注意的是id 是一个指针,所以在使用id的时候不需要加星号,比如,
id foo=nil;

上述语句定义了一个nil 指针,这个指针指向NSObject 的任意一个子类。

而“id *foo=nil;”则定义了一个指针,这个指针指向另一个指针,被指向的这个指针指向NSObject的一个子类。

id 是Objective-C中的一个特殊的数据类型,还有nil、Nil、SEL…

他们中的大多数都可以在/usr/include/objc/objc.h或者这个目录中的其他头文件中找到。

typedef struct objc_class Class;
typedef struct objc_object {
Class isa;
}
id;

(2) NSObject,NSObject 本身就是定义指向NSObject类型的指针.
NSObject
就是 NSObject类型的指针了,它范围较小。
NSObject对象会惊醒编译时检查(需要强制类型转换)

(3) 然后让我们来总结下id 与 NSObject 区别:
从编译时来看:
1,id关键字在编译时不被检查,而NSObject在编译时会被检查是否被调用一些错误方法。
从范围上来看:
2,id可以是任何对象,包括非NSObject对象
从定义上来看:
3,定义id的时候不使用*,NSObject却需要。
我的理解,基本上来讲,定义id类似于定义了一个地址(只有指针,抽象指针),而NSObject是确实的定义了一个逻辑对象的地址。

(4).id<NSObject>
id<NSObject>告诉编译器,你不关心对象是什么类型,但它必须遵守NSObject协议(protocol),编译器就能保证所有赋值给id<NSObject>类型的对象都遵守NSObject协议(protocol)。这样的指针可以指向任何NSObject对象,因为NSObject对象遵守NSObject协议(protocol),而且,它也可以用来保存NSProxy对象,因为它也遵守NSObject协议(protocol)。这是非常强大,方便且灵活,你不用关心对象是什么类型,而只关心它实现了哪些方法。

(5)instancetype

instancetype是clang 3.5开始,clang提供的一个关键字,表示某个方法返回的未知类型的Objective-C对象。我们都知道未知类型的的对象可以用id关键字表示,那为什么还会再有一个instancetype呢?

instancetype 是一个关键字,它只能用来定义OC方法的返回值类型。

使用 instancetype 编译器和IDE 会做类型检查,而id不会做完整的类型检查。

用instancetype代替id作返回类型有什么好处
1、明确性。代码只做你让它做的事,而不是其他。
2、程式化。你会养成好习惯,这些习惯在某些时候会很有用,而且肯定有用武之地。
3、一致性。让代码可读性更好。
连接
连接
连接

它和id比较:

相同点
都可以作为方法的返回类型
不同点
1 instancetype可以返回和方法所在类相同类型的对象,id只能返回未知类型的对象;
2 instancetype只能作为返回值,不能像id那样作为参数

总结:instancetype更加智能,编译器知道要返回什么类型,而id则不能,所以以后尽量用 instancetype

以下链接是参考和扩展:
Object-C 类,对象,运行时,isa
连接

动态类型 动态绑定 动态载入 SEL类型:
连接

Objective-C中的id这种数据类型存在的价值是什么?:
连接

iOS数据类型:
连接

Objective-C id 数据类型:
连接

Objective-C中的一些特殊的数据类型 id、nil、Nil、SEL:
连接

Objective-C中的id类型:
连接

如何才能系统的学习 iOS 开发,理解一些规则和深层次的机制原理?
连接

iOS开发中很重要,很常用,但却容易被忽略的知识点:id ,NSObject, id区别
连接

第一次接触OC多态,动态类型与动态绑定 - 小四也软开
连接

C语言基本数据类型简介
连接

Objective-C的内省(Introspection)机制小结
明智地使用内省可以使面向对象的程序更加高效和强壮。
它有助于避免错误地进行消息派发、错误地假设对象相等、以及类似的问题。
连接

Objective-C语法之动态类型(isKindOfClass, isMemberOfClass,id)等
对象在运行时获取其类型的能力称为内省。内省可以有多种方法实现。
连接

在C++中我们知道void*是一个万能指针,或者是叫通用对象,
那么在OC中也有这样一个类似作业的通用对象,叫做id,id是OC中的万能指针,它可以指向任何类型的对象。
如果receiver是id类型,在运行之前编译器是不会给出警告的,因为编译器不知道id中是什么类型,
当程序运行时id中保存对象类型确定,这个时候id的类型也就是消息这个对象的类型。
要是对象所属类中没找到这个类型,运行时程序会有问题
比如说
传递给id的类型是A类型,要是这个类中没有A类型,那么这个程序就会有问题。

Objective-C学习之动态绑定和id类型
连接

id和NSObject *和instanceType的区别与联系 - 顺子为王
连接

iOS中id与NSObject* 和id的区别
连接

id类型的使用与NSObject区别
连接

id 与 NSObject 区别
连接

强类型语言和弱类型语言
连接

instancetype、id、NSObject的区别
连接

instancetype
连接

像这种细节性的问题,一般浮躁的或者不去留心观察的人,不多问几个为什么的人,没有使用次数多的人,是不太会去关注这几个关键字的区别的,这也就是很多程序员之间的差异。思考多的 深入的人,往往能够看得更深入透彻一些,在实际运用中也能更加灵活,更加的有较好的选择性,大多数的问题都可以到网上搜到,但是别人遇到的问题毕竟不是自己的,我们也没有经过那个过程,所以还是勤奋点 多让自己接触点,这样知识涉及的多,思考的也就多了,善于利用搜索引擎和思考实践总结。编程学的其实越来越像一种思维方式了(个人感觉),但是光思考是不行的,最最重要的还是行动去实践检验探究,这样才会变得更加强大,所以大家一起来探讨深入研究吧 哈哈 再絮叨一句 个人感觉这些东西就像金钱一样,掌握的尽可能越多越好,因为以后用到钱用的这些知识的地方会很多,不要等到那个时候再去学再去攒钱或想着一夜致富啥的就太晚了,不要浮躁享受积累的力量吧。