转自:http://blog.csdn.net/happytengfei/article/details/11473931

我们经常会混淆以下三种申明(我是没有留意过):
    1. id foo1;
    2. NSObject *foo2;
    3. id<NSObject> foo3;

第一种是最常用的,它简单地申明了指向对象的指针,没有给编译器任何类型信息,因此,编译器不会做类型检查。但也因为是这样,你可以发送任何信息给id类型的对象。这就是为什么+alloc返回id类型,但调用[[Foo alloc] init]不会产生编译错误。

因此,id类型是运行时的动态类型,编译器无法知道它的真实类型,即使你发送一个id类型没有的方法,也不会产生编译警告。

我们知道,id类型是一个Objective-C对象,但并不是都指向继承自NSOjbect的对象,即使这个类型和NSObject对象有很多共同的方法,像retain和release。要让编译器知道这个类继承自NSObject,一种解决办法就是像第2种那样,使用NSObject静态类型,当你发送NSObject没有的方法,像length或者count时,编译器就会给出警告。这也意味着,你可以安全地使用像retain,release,description这些方法。

因此,申明一个通用的NSObject对象指针和你在其它语言里做的类似,像java,但其它语言有一定的限制,没有像Objective-C这样灵活。并不是所有的Foundation/Cocoa对象都继承息NSObject,比如NSProxy就不从NSObject继承,所以你无法使用NSObject*指向这个对象,即使NSProxy对象有release和retain这样的通用方法。为了解决这个问题,这时候,你就需要一个指向拥有NSObject方法对象的指针,这就是第3种申明的使用情景。

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

现在你知道你要用什么类型了不?

如果你不需要任何的类型检查,使用id,它经常作为返回类型,也经常用于申明代理(delegate)类型。因为代理类型通常在运行时,才会检查是否实现了那些方法。

如果真的需要编译器检查,那你就考虑使用第2种或者第3种。很少看到NSObject*能正常运行,但id<NSObject>无法正常运行的。使用协议(protocol)的优点是,它能指向NSProxy对象,而更常用的情况是,你只想知道某个对象遵守了哪个协议,而不用关心它是什么类型。

更具体的:

1. 我们来看看id的定义,它就是一个指针,它可以指向的类型不仅限于NSObject

[代码]c#/cpp/oc代码:

1 typedef struct objc_class *Class;
2 typedef struct objc_object {
3     Class isa;
4 } *id;
 
2. NSObject*就是 NSObject类型的指针了,它范围较小。
 
3. id<NSObject>是指针,它要求它指向的类型要实现NSObject protocol,
iOS中很多类定义很奇葩,类名叫NSObject,定义个接口也叫NSObject,但是它俩不是一个东东。
 
而NSObject类实现了NSOject接口,所以id<NSObject>可以指向NSObject的对象。
NSObject实现类似这样:

[代码]c#/cpp/oc代码:

1 @interface NSObject <NSObject> {
2     Class isa;
3 }
4
 
如果我们来看看NSProxy的定义,你会发现,它不是继承自NSObject,但是却实现了NSObjecct接口,
NSProxy定义类似这样:

[代码]c#/cpp/oc代码:

1 @interface NSProxy <NSObject> {
2     Class   isa;
3 }
4
所以id<NSObject>可以指向NSProxy的对象。

转自:http://www.cocoachina.com/bbs/read.php?tid=151376&page=e

http://www.devdiv.com/ios_id_nsobject_id_lt_nsobject_gt_-blog-1-50764.html

id ,NSObject, id<NSObject>区别的更多相关文章

  1. IOS_OC_id ,NSObject, id&lt;NSObject&gt;差别

    我们常常会混淆下面三种申明(我是没有留意过):     1. id foo1;     2. NSObject *foo2;     3. id<NSObject> foo3;     第 ...

  2. html元素中id和name的区别

    可以说几乎每个做过Web开发的人都问过,到底元素的ID和Name有什么区别阿?为什么有了ID还要有Name呢?! 而同样我们也可以得到最classical的答案:ID就像是一个人的身份证号码,而Nam ...

  3. Android @id和@+id区别

    Android中的组件需要用一个int类型的id属性值来表示.id属性只能接受资源类型的值,也就是必须以@开头的值,例如,@id/abc.@+id/xyz等.如果在@后面使用“+”,表示当修改完某个布 ...

  4. Android查缺补漏(View篇)--布局文件中的“@+id”和“@id”有什么区别?

    Android布局文件中的"@+id"和"@id"有什么区别? +id表示为控件指定一个id(新增一个id),如: <cn.codingblock.vie ...

  5. html中元素的id和name的区别(2016-1-22)

    HTML中元素的Id和Name属性区别 一直以来一直以为在html中,name和id没什么区别,今天遇到一个坑才发现(PHP获取不到表单数据,原因:元素没有name,只定义了id),这两者差别还是很大 ...

  6. form表单中的id 与name的区别

    以前经常写form表单时,不写id和name,总觉得没有什么用.后来一看后台套完的页面发现,他们都补上name,不知道所以然,就查了一下资料,吓我一跳,要是照我那样写根本不会有数据传到服务器.原来表单 ...

  7. html中id name class的区别(转)

    HTML 中 id与name 区别 一个name可以同时对应多个控件,比如checkbox和radio 而id必须是全文档中唯一的 id的用途 1) id是HTML元素的Identity,主要是在客户 ...

  8. javascript querySelector和getElementById通过id获取元素的区别

    querySelector和getElementById通过id获取元素的区别 <!DOCTYPE html> <html> <head> <meta cha ...

  9. id和class的区别

    id和class是定义css样式用到的,不同的是定义样式时的写法不一样,使用id选择样式时,定义的格式为 #main{width:20px;} ,使用class时用到的是 .main{width:20 ...

随机推荐

  1. 集成SVN源码管理和Mantis缺陷跟踪

    集成SVN源码管理和Mantis缺陷跟踪 (windows) 要集成Mantis和SVN,需要几个工具:SVN客户端,TortoiseSVN,下载地址: http://tortoisesvn.net/ ...

  2. [Gradle] Gradle 构建工具的未来

    转载地址:http://www.infoq.com/cn/news/2011/04/xxb-maven-6-gradle Maven面临的挑战 软件行业新旧交替的速度之快往往令人咂舌,不用多少时间,你 ...

  3. 用Latex写IEEE论文

    如果在搞科研,想在IEEE上发表文章,那么就不得不用IEEE的论文模板,分为doc版本和Tex版本.Tex是高德纳·纳什所写,大牛级的任务,写过<计算机程序设计艺术>,曾经是美国最年轻的科 ...

  4. 数学图形(1.20)N叶草

    有N个叶子的草 相关软件参见:数学图形可视化工具,使用自己定义语法的脚本代码生成数学图形.该软件免费开源.QQ交流群: 367752815 vertices = t = to (*PI) r = n ...

  5. PowerDesigner概念设计模型(CDM)中的3种实体关系

    CDM 是大多数开发者使用PD时最先创建的模型,也是整个数据库设计最高层的抽象.CDM是建立在传统的ER图模型理论之上的,ER图中有三大主要元素: 实体型,属性和联系.其中实体型对应到CDM中的Ent ...

  6. go语言基础之递归实现数字累加

    1.实现1+100 = 5050 示例: package main import "fmt" //实现1+2+3+……100 func test01() (sum int) { f ...

  7. 统计的一个小题目python实现

    最近面试碰到的一个题目,业余时间用python实现的. 拿到数据,先用sort 命令排序,也可再进一步去重复 sort -k 1,2  data.txt |uniq  > data.new # ...

  8. dTree无限级文件夹树和JQuery同步Ajax请求

    曾经都是用JQuery对树的支持来实现文件夹树的,近来闲来无事就弄了下dTree,感觉其无限级文件夹还是挺好的,并且它的使用也比較方便,基本上就是先把要用的js文件即dtree.js和css文件dtr ...

  9. [Grunt] Uglify

    Grunt Uglify to compress your javascript for production deployment. Install npm install grunt-contri ...

  10. sqlserver并发用户数

    http://zhidao.baidu.com/question/291231462.html http://dev.mysql.com/downloads/mysql/