iOS开发-id、instancetype、NSObject *和id<NSObject> *的区别

卢鸿博
2023-12-01

首先需要知道,在cocoa的开发环境里,NSObject是所有类的根类。

1、id

id的定义:

typedef struct objc_object {
    Class isa;
} *id;

从定义来看,id就是一个isa指针,可以指向任何一个继承了Object(或者NSObject)类的对象,所以id可以指向任何一个cocoa的合法对象,id可以简单理解为一个万能指针。

id是动态数据类型,编译时编译器不会检查id对象的类型,只有在运行时动态检查后会报错。

id可以用于

  • 定义变量;
  • 定义方法返回值;
  • 定义方法参数。
-(id) loadDataWithThings:(id)things {
    id anyThing = things;
    return anyThing;
}

2、instancetype

instancetype意思为实例化,instancetype与和id一样,都可以指向一个继承了Object(或者NSObject)类的对象。

区别在于:instancetype只能作为方法返回值,需要返回该方法所在的类的实例化对象,所以instancetype也被称为关联返回类型。

使用instancetype会在编译时进行类型检查,有利于开发者在编译阶段发现错误。

根据 Cocoa 的命名规则,满足下述命名规则的方法应该返回该方法所在类的实例化对象,这些方法被称为是关联返回类型的方法:

  • 以 alloc 或 new 开头的类方法
  • 以 autorelease、init、retain 或 self 开头的实例方法。

例如:

+ (instancetype)alloc;
- (instancetype)init;
//因此这里alloc和init返回的类型都是NSArray*
NSArray *arr = [[NSArray alloc]init];

instancetype的正确使用姿势

3、NSObject *

@interface NSObject <NSObject> {
    Class isa  OBJC_ISA_AVAILABILITY;
}

从定义来看,NSObject* 就是指向NSObject类型的指针了,可以指向任何一个继承了NSObject的对象,感觉和上面的id、instancetype也没有区别。

区别在于NSObject* 是静态数据类型,编译时会进行类型检查。

NSObject*的作用与id一致。

4、id<NSObject> *

id<NSObject> *就是指该对象的类型可以是任何一个NSObject或继承了NSObject的子类,但该对象必须要遵循<NSObject>协议(奇葩的命名:协议名与类名一样)。简单来说就是它不关心对象是什么类型,只要遵循<NSObject>协议即可。

在定义delegate时常用。

 类似资料: