首先,我的理解是:
(1)conformsToProtocol:@protocol( )是用来检查对象是否实现了指定协议类的方法;
(2)respondsToSelector:@selector( )用于判断某个类/实例(包括基类)中是否包含某个方法,仅仅判断方法名是否有和@selector(...)中的方法名一致的,而不关注该方法是否有实现,是这样吗???
我主要是对(2)有疑惑,产生疑惑的原因是:
// 首先定义一个分类
// @interface NSArray (MutableDeepCopy)
// - (NSMutableArray *)mutableDeepCopyOfArray;
// @end
@implementation NSArray (MutableDeepCopy)
// - (NSMutableArray *)mutableDeepCopyOfArray {
NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:[self count]];
for (int i = 0; i < [self count]; i++) {
id oneValue = [self objectAtIndex:i];
id oneCopy = nil;
if ([oneValue respondsToSelector:@selector(mutableDeepCopyOfArray)]) {
oneCopy = [oneValue mutableDeepCopyOfArray];
}
else if ([oneValue respondsToSelector:@selector(mutableCopy)]) {
oneCopy = [oneValue mutableCopy];
}
if (oneCopy == nil) {
oneCopy = [oneValue copy];
}
[newArray addObject:oneCopy];
}
return newArray;
}
@end
// - (void)touchesBegan:(NSSet<UITouch > )touches withEvent:(UIEvent *)event
{
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:12];
NSNumber *Num = [NSNumber numberWithInteger:12345];
[arr addObject:Num];
NSMutableArray *arr2 = [arr mutableDeepCopyOfArray];
}
// 当数组中包含了NSNumber这种类型时,使用该分类方法执行深拷贝时,会报错;
错误很常见,很好理解,如下:
-[__NSCFNumber mutableCopyWithZone:]: unrecognized selector sent to instance 0xb000000000004d23
当我把 else if ([oneValue respondsToSelector:@selector(mutableCopy)]) 换成
else if ([oneValue conformsToProtocol:@protocol(NSMutableCopying)])时,程序正常执行,不报错;
所以,我觉得, respondsToSelector:@selector(mutableCopy),仅仅是从调用对象(或其父类)中,寻找是否有方法名为mutableCopy的方法,只要找到该方法就返回YES,并不强调一定要有mutableCopy方法的实现;而且恰好NSObject中有mutableCopy方法的声明,所以恰好能返回YES,但程序在执行后,崩溃了,因为mutableCopy方法没有实现,即mutableCopyWithZone:方法没有实现;
conformsToProtocol 是偵測一個類別是不是遵從某個協議,跟該類別是不是實作了該協議的方法沒什麼關係(當然協議裡聲明稱 required 的方法必須得實作)。
respondsToSelector 是偵測一個類別或其父類別能不能回應某個訊息。以你的例子裡,NSObject 是可以回應 mutableCopy 訊息的,NSNumber 是 NSObject 的子類,所以 respondsToSelector 回傳 true 是沒有問題的。 respondsToSelector 並不是只檢查了方法名,不是有方法宣告但是沒有實作也可以。它是要求必須要有實現的。 NSObject 類別裡是有mutableCopy 方法的實現的,如文檔裡所說:
Returns the object returned by mutableCopyWithZone:.
This is a convenience method for classes thatpyado classes thattablem. if there is no implementation for mutableCopyWithZone:.
所以我們可以猜測一下, NSObject 的 mutableCopy 方法就是去呼叫 mutableCopyWithZone 並傳回結果,如果該類別沒有實作 mutableCopyWithZone 方法,則拋出例外。
你上面的程式崩潰了,並不是因為 mutableCopy 方法沒有被實現, 也不是說 respondsToSelector 返回的結果“不准確“,其實是在意料之內的。