`
janedoneway
  • 浏览: 583162 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

id vs NSObject vs id<NSObject>

 
阅读更多

From: http://hi.baidu.com/colorapple/blog/item/bc40470a87763d34b0351d1f.html

 

 

There's often confusion about the difference between the following three declarations in Objective-C:


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


The first one is the most common. It simply declares a pointer to some Objective-C object (see /usr/include/objc/objc.h). id gives the compiler no information about the actual type of the object, so the compiler cannot do compile-time type checking for you. Thus, the compiler will let you send any (*) message to objects declared id. Actually, this is why the common idiom of [[Foo alloc] init] doesn't cause the compiler to complain. +alloc is declared to return type id, so the compiler won't yell when you then send the returned object the message init (or even initWithMyFoo:blah).

So, objects declared using id are just dynamically typed at runtime. The compiler has no useful information about the object's real type, so it can't warn you if you send it a message that it may not respond to.

Just because we know that an id is an Objective-C object does not mean that it points to an object that derives from NSObject, or that it even has common methods like retain and release. One solution is to statically type our variable using NSObject* as shown in number 2 above. This gives the compiler information about the class of the object pointed to by foo2 so the compiler can warn if you send a message to foo2 that an NSObject doesn't respond to. This means you can safely call retain, release, description, etc., but the compiler will warn if you call length or count or anything that an NSObject doesn't respond to.

So, declaring a generic pointer of type NSObject* is very similar to what you would do in other languages, like Java, but it's really a bit too restrictive for a language as flexible as Objective-C. Despite what you may have learned at one point, not all Foundation/Cocoa objects derive from NSObject. As an example, NSProxy is not derived from NSObject, so the foo2 pointer above would not be able to hold an NSProxy subclass, even though NSProxy does implement common methods like retain and release. What you really want is a pointer to any object that behaves like an NSObject. And that's exactly what the third case does.

Declaring an object as id<NSObject> tells the compiler that you don't care what type the object is, but you do care that it conforms to the specified NSObject protocol**. The compiler will ensure that all objects you assign to that pointer conform to the required protocol. A pointer typed like this can safely hold any NSObject (because NSObject conforms to the NSObject protocol), but it could also hold any NSProxy, because NSProxy also conforms to the NSObject protocol. In english, the declaration id<NSObject> foo3; says "foo3 is a pointer to an object of any type that behaves like an NSObject". This is very powerful, convenient, and expressive. In reality, we often don't care what type an object is, we just care that it responds to the messages that we want to send it (e.g., retain, release).

So how do you decide which form you want to use? It's pretty easy. If you don't want (or can't have) any type checking, then use a plain id. This is very common for return types on methods that don't know the type of object they're returning (e.g., +alloc). It is also common to declare delegates to be type id, because delegates are generally checked at runtime with respondsToSelector:, and they usually aren't retained.

However, if you do want compile-time type checking, you must decide between the second and third cases. Well, let me just help you out—you want the third case! :-) I've very, very, VERY rarely seen a situation where NSObject * worked but id<NSObject> would not. And using the protocol form has the advantage that it will work with NSProxys. You may think that you never use NSProxys, but Cocoa's distributed objects system makes heavy use of NSProxy subclasses. Additionally, the common case is that you simply want to ensure that an object can be retained or released, and in that case the protocol form conveys that intent better; you really don't care what class the object is, you only care that it behaves like an NSObject.

分享到:
评论

相关推荐

    iOS开发UI篇—字典转模型 - 文顶顶 - 博客园

    &lt;key&gt;id&lt;/key&gt; &lt;integer&gt;158&lt;/integer&gt; &lt;key&gt;name&lt;/key&gt; &lt;string&gt;应用1&lt;/string&gt; &lt;key&gt;version&lt;/key&gt; &lt;integer&gt;0&lt;/integer&gt; &lt;!-- 其他相关信息 --&gt; &lt;/dict&gt; &lt;!-- 更多的字典条目 --&gt; &lt;/array&gt; ``` 开发...

    iOSXML数据解析

    &lt;book id="bk101"&gt; &lt;author&gt;Gambardella, Matthew&lt;/author&gt; &lt;title&gt;XML Developer's Guide&lt;/title&gt; &lt;genre&gt;Computer&lt;/genre&gt; &lt;price&gt;44.95&lt;/price&gt; &lt;publish_date&gt;2000-10-01&lt;/publish_date&gt; &lt;description&gt;An...

    ios中工厂方法的完美实现

    @interface ConcreteProductA : NSObject &lt;ProductProtocol&gt; @end @implementation ConcreteProductA -(void)execute { NSLog(@"ConcreteProductA is executing."); } @end @interface ConcreteProductB : ...

    iOS中XML解析 (一) TBXML (实例:打印xml内容及存储到数组)

    &lt;book id="1"&gt; &lt;title&gt;书名1&lt;/title&gt; &lt;author&gt;作者1&lt;/author&gt; &lt;/book&gt; &lt;book id="2"&gt; &lt;title&gt;书名2&lt;/title&gt; &lt;author&gt;作者2&lt;/author&gt; &lt;/book&gt; &lt;/books&gt; ``` 我们可以使用TBXML来打印XML的内容: ```objc ...

    Objective C 中介者模式设计源码

    - (void)colleague:(id&lt;Colleague&gt;)colleague performAction:(NSString *)action; @end // ConcreteMediator类 @interface ConcreteMediator : NSObject &lt;Mediator&gt; @property (nonatomic, strong) NSMutableArray ...

    iPhone编程解析xml

    @interface YourXMLParser : NSObject &lt;NSXMLParserDelegate&gt; @property (nonatomic, strong) NSMutableArray&lt;Item *&gt; *items; @end @implementation YourXMLParser - (void)parser:(NSXMLParser *)parser ...

    分页效果设置

    @protocol ZSegmentedControlDelegate &lt;NSObject&gt; - (void)setSelectedIndex:(NSUInteger)selectedIndex; @end typedef NS_ENUM(NSInteger, MSegmentedControlIndicatorStyle){ ...

    【IOS一气呵成】之IAP集成:内购和内购恢复 DEMO

    #import &lt;Foundation/Foundation.h&gt; ...@property(nonatomic,assign) id&lt;RMIAPHelperDelegate&gt; delegate; -(void)setup; -(void)destroy; -(void)buy:(NSString*)productId; -(void)restore; @end

    探索NSObject的协议精髓:Objective-C中的基础方法解析

    #import &lt;Foundation/Foundation.h&gt; @interface MyObject : NSObject @property (nonatomic, strong) NSString *name; @end // MyObject.m #import "MyObject.h" @implementation MyObject - (instancetype)...

    Objective C简单工厂模式设计源码

    @protocol CalculatorProtocol &lt;NSObject&gt; @required - (NSNumber *)add:(NSNumber *)num1 with:(NSNumber *)num2; - (NSNumber *)subtract:(NSNumber *)num1 from:(NSNumber *)num2; @end ``` 接下来,我们可以...

    objective-c之委托协议

    `&lt;NSObject&gt;`表示这个协议继承自内置的`NSObject`协议,这样我们可以使用`NSObject`的方法,如`isEqual:`和`description`。 然后,创建一个类(如`EventProcessor`),它将使用委托来处理事件。在`EventProcessor`...

    iOS应用开发中使用设计模式中的观察者模式的实例

    @property (nonatomic, strong) NSMutableArray&lt;id&lt;ObserverProtocol&gt;&gt; *observers; - (void)attachObserver:(id&lt;ObserverProtocol&gt;)observer; - (void)detachObserver:(id&lt;ObserverProtocol&gt;)observer; - (void)...

    iOS NSObject对象的本质、内存分配、ISA指针及superclass底层源码分析.pdf

    iOS NSObject对象的本质、内存分配、ISA指针及superclass底层源码分析 iOS NSObject对象是iOS开发中最基本也是最重要的对象之一,我们在使用它时往往只是停留在会用的阶段,却没有深入了解过它的本质。今天我们就来...

    OC-工厂模式-处理不同通知

    - (id&lt;NotificationObserver&gt;)createObserverForNotificationType:(NSString *)notificationType; @end ``` #### 4.2 创建具体工厂 接着,创建具体工厂类实现这个协议,例如`DefaultNotificationObserverFactory`:...

    iOS实现轮播图banner示例

    楼主项目中需要有一个轮播图,因为比较简单,就自己写了个,因为是从网上弄得图片 所以用了SDWebImage 这个三方库 当然自己也可以去掉 类型后面有*号 如用使用 请自行...@property (nonatomic,weak)id&lt;TJXViewDelegate&gt;

    JSON到NSObject的映射库Motis.zip

     @"user_id": mts_key(userId),  @"creation_date": mts_key(creationDate),  @"website": mts_key(website),  @"user_stats.views": mts_key(views), // &lt;-- KeyPath access  @"user_stats.ranking":...

    详解Objective-C编程中对设计模式中适的配器模式的使用

    @interface ObjectAdapter : NSObject&lt;Target&gt; @property (nonatomic, weak) id&lt;Adaptee&gt; adaptee; @end @implementation ObjectAdapter - (void)Request { [self.adaptee SpecificRequest]; } @end ``` 在这个...

    Objective C 策略模式设计源码

    @property (nonatomic, strong) id&lt;AlgorithmProtocol&gt; algorithm; - (void)performAction; @end @implementation Context - (void)performAction { [self.algorithm execute]; } @end ``` 4. **使用策略**:在...

    CompositePattern:设计模式之组合模式

    @property (nonatomic, strong) NSMutableArray&lt;id&lt;CompositeProtocol&gt;&gt; *children; - (void)performOperation; @end ``` 在Objective-C中,组合模式的实现通常涉及以下几个步骤: 1. 定义Component协议或基类。 2...

    ios代理传值

    @property (nonatomic, weak) id&lt;PassValueDelegate&gt; delegate; - (void)sendValue:(NSString *)value; @end ``` 在`ValueSender`类中实现`sendValue:`方法,通过代理将值传递出去: ```objc @implementation ...

Global site tag (gtag.js) - Google Analytics