在很早之前编译器没有提供instancetype
关键字,我们在写函数/方法返回值时都用的是id
。clang编译器有了instancetype
之后,让我们的代码能够更加严谨且高效。
instancetype
和id
的最大区别就是编译时期的类型检测,而且instancetype
不能作为参数类型传递。
类型检测
例:
1 | // 声明类 |
方式一(使用id):
1 | @implementation YBPerson |
使用NSArray类型指针接收
1
2NSArray *person = [[YBPerson alloc] initWithName:@"idbeny"];
NSLog(@"%ld", [person count]);编译,没问题
运行,崩溃(因为YBPerson的实例没有找到count这个方法)
1
[YBPerson count]: unrecognized selector sent to instance 0x60000382ca40
方式一(改造):
使用YBPerson类型指针接收
1
2NSArray *person = [[YBPerson alloc] initWithName:@"idbeny"];
NSLog(@"%ld", [person count]);编译器警告
1
Incompatible pointer types initializing 'NSArray *' with an expression of type 'YBPerson *'
运行,崩溃(因为YBPerson的实例没有找到count这个方法)
1
[YBPerson count]: unrecognized selector sent to instance 0x60000382ca40
方式二(使用instancetype):
1 | @implementation YBPerson |
使用NSArray指针接收:
1
2NSArray *person = [[YBPerson alloc] initWithName:@"idbeny"];
NSLog(@"%ld", [person count]);编译器警告
1
Incompatible pointer types initializing 'NSArray *' with an expression of type 'YBPerson *'
运行,崩溃(因为YBPerson的实例没有找到count这个方法)
1
[YBPerson count]: unrecognized selector sent to instance 0x60000382ca40
通过上面的案例说明,使用id
和instancetype
都可以作为返回值使用,instancetype
可以在编写代码时就能检测类型匹配问题,而id
是不可以的。
参数类型传递
instancetype
作为参数类型
1 | - (instancetype)initWithName:(instancetype)name; |
编译报错
1 | Expected a type |
id
作为参数类型
1 | - (instancetype)initWithName:(id)name; |
编译,运行,都没有问题。所以,id
可以作为参数的类型传递,instancetype
不可以。