iOS Object-C的id与instancetype关键字的异同点

在写一个单例方法的时候,被问到为什么返回值类型用instancetype而不用id

+ (instancetype)shareManager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _shareManager = [[super allocWithZone:NULL] init];
    });
    
    return _shareManager;
}

其实听到这个问题,懵了一下,一直以为就是这么用。至于为什么,没有深入考虑过,只是觉得这么用好,那就继续用吧。所以用了很长时间之后,依旧不知道为什么。

一、 idinstancetype概念问题

首先确认instancetype是什么:instancetype是clang 3.5开始,clang提供的一个关键字,表示某个方法返回的未知类型的Objective-C对象。

其次,id是什么:id 是一种通用的对象类型,它可以指向属于任何类的对象,也可以理解为万能指针 ,相当于C语言的 void *

idinstancetype都可以用来表示未知类型的对象,instancetype只是用于返回值,但是id可以用于返回值、参数和变量。

二、相关概念:关联返回类型(related result types)方法,非关联返回类型方法。

根据Cocoa的命名规则,满足下述规则的方法:1、类方法中,以allocnew开头,2、实例方法中,以autoreleaseinitretainself开头。会返回一个方法所在类类型的对象,这些方法就被称为是关联返回类型的方法。(这些方法的返回结果以方法所在的类为类型)。

除此之外的方法,返回的类型就是方法声明的返回类型。

做一个简单的试验:

// 声明一个实例 继承自NSObject
@interface TestObject : NSObject
+ (id)shareWithId; // 非关联方法,返回类型id
+ (instancetype)shareWIthInstancetype; // 非关联方法,返回类型为当前类TestObject。
@end

>>>>

// 调用两个类方法,并同时使用获得的对象调用任意一个系统方法

[[TestObject shareWithId] removeAllObjects];
// TestObject shareWithId]返回类型为id通用类型,所以编译器不会验证TestObject是否实现removeAllObjects方法。不会报错。
// 但是在运行时,会产生崩溃:-[TestObject objCType]: unrecognized selector sent to instance 0x600000cec570

[[TestObject shareWIthInstancetype] removeAllObjects];
// [TestObject shareWIthInstancetype]返回TestObject类型对象,编译器会验证该方法是否实现,未实现则会报错。
// 错误:No visible @interface for 'TestObject' declares the selector 'removeAllObjects'

在这里插入图片描述

这里主要说明两个问题:
1、非cocoa命名规则下的关联返回类型的方法(自定义快速构造方法)返回的类型是方法声明的返回类型。
2、instancetype的作用,就是使那些非关联返回类型的方法返回所在类的类型。即可以将非关联返回类型方法,在编译的时候确定对象的真实类型。避免一些问题在运行处才会暴露。

三、结论和建议

  • idinstancetype都可以用来表示未知类型的对象。
  • id在编译的时候不能确定对象的真实类型,instancetype在编译的时候能确定对象的真实类型。
  • id可以用来定义变量、参数、返回值, instancetype只能用于作为返回值。
  • 在调用系统类的初始化方法allocinit会自动将id转换成instancetype。不过在自定义构造方法时,建议直接使用instancetype
  • 单例中的单例方法使用instancetype

参考:
https://blog.csdn.net/yaoliangjun306/article/details/53726282
https://blog.csdn.net/baidu_28787811/article/details/80545552
http://tewha.net/2013/02/why-you-should-use-instancetype-instead-of-id/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值