在Objective-C 中,id 类型是一个独特的数据类型。在概念上,类似Java 的Object 类,可以转换为任何数据类型。换句话说,id 类型的变量可以存放任何数据类型的对象。在内部处理上,这种类型被定义为指向对象的指针,实际上是一个指向这种对象的实例变量的指针。例如,下面定义了一个id类型的变量和返回一个id类型的方法:
1 id anObject;
2 - (id) newObject: (int) type;
id 和void *并非完全一样。下面是id在objc.h中的定义:
1 typedef struct objc_object {
2 Class isa;
3 } *id;
从上面看出,id 是指向struct objc_object 的一个指针。也就是说,id 是一个指向任何一个继承了Object(或者NSObject)类的对象。需要注意的是id 是一个指针,所以在使用id的时候不需要加星号,比如,
1 id foo=nil;
上述语句定义了一个nil 指针,这个指针指向NSObject 的任意一个子类。而“id*foo=nil;”则定义了一个指针,这个指针指向另一个指针,被指向的这个指针指向NSObject的一个子类。
在Objective-C中,id取代了int类型成为默认的数据类型(在C语言中,int是默认的函数返回值类型),关键字nil 被定义为空对象,也就是值为0 的对象。关于更多的Objective-C基本类型,读者可以参考obj/objc.h文件。
id类型是运行时的动态类型,编译器无法知道它的真实类型,即使你发送一个id类型没有的方法,也不会产生编译警告。
id 还可以表示基础类型,但是不能表示float,double类型
· 用于描述delegate的类型,比如对于tableView来说其只知道自己的delegate是继承自UITableViewController的对象,但并不关心delegate具体的类型,只需要知道delegate是不是实现了那几个协议required方法就行了,这时候无法也没必要让tableView知道delegate的具体类型。
· 容器类的遍历,对于Array来说似乎也不用关心自己包含哪些类型的对象,因此枚举迭代只需要知道有对象就可以了,至于枚举这些对象用来干什么那是程序员自己的事情。
多态情况下因为继承的原因可以依赖父类,但是没有继承关系的时候,就无法确定对象类型,这个时候就可以用id。
比如你设计一个类的delegate,你设计的时候根本无法确定什么对象来做你的delegate,于是可以用id,表示任何类型对象都欢迎。
http://blog.youkuaiyun.com/lonelyroamer/article/details/7711895
https://www.zhihu.com/question/22814649