首先,我的理解是:
(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 consiste à détecter si une classe est conforme à un certain protocole. Cela n'a rien à voir avec le fait que la classe implémente la méthode du protocole (bien sûr, la méthode déclarée requise dans le protocole doit être implémentée).
respondsToSelector sert à détecter si une classe ou sa classe parent peut répondre à un certain message. Dans votre exemple, NSObject peut répondre aux messages mutableCopy et NSNumber est une sous-classe de NSObject, il n'y a donc aucun problème avec le retour de responsToSelector true. responsToSelector ne vérifie pas seulement le nom de la méthode, peu importe s'il existe une déclaration de méthode mais pas d'implémentation. C’est une exigence qui doit être mise en œuvre. La classe NSObject a une implémentation de la méthode mutableCopy, comme indiqué dans la documentation :
Renvoie l'objet renvoyé par mutableCopyWithZone :.
Il s'agit d'une méthode pratique pour les classes qui adoptent le protocole NSMutableCopying. Une exception est levée s'il y a. il n'y a pas d'implémentation pour mutableCopyWithZone:.
Nous pouvons donc deviner que la méthode mutableCopy de NSObject consiste à appeler mutableCopyWithZone et à renvoyer le résultat. Si la classe n'implémente pas la méthode mutableCopyWithZone, une exception sera levée.
Votre programme ci-dessus s'est écrasé non pas parce que la méthode mutableCopy n'était pas implémentée, ni parce que cela ne signifiait pas que le résultat renvoyé par responsToSelector était "inexact". Il était en fait attendu.