首先,我的理解是:
(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 は、クラスが特定のプロトコルに準拠しているかどうかを検出するものであり、クラスがそのプロトコルのメソッドを実装しているかどうかとは関係ありません (もちろん、プロトコルで必須と宣言されているメソッドは実装されている必要があります)。
respondsToSelector は、クラスまたはその親クラスが特定のメッセージに応答できるかどうかを検出します。あなたの例では、NSObject は mutableCopy メッセージに応答でき、NSNumber は NSObject のサブクラスであるため、respondsToSelector が true を返すことに問題はありません。 respondsToSelector はメソッド名をチェックするだけではなく、メソッド宣言はあっても実装がない場合でも問題ありません。これは実装する必要がある要件です。ドキュメントに記載されているように、NSObject クラスには mutableCopy メソッドの実装があります。
の実装ではありませんmutableCopyWithZone: によって返されるオブジェクトを返します。
これは NSMutableCopying プロトコルを採用するクラスの便利なメソッドです。存在する場合は例外が発生します。 mutableCopyWithZone:.
したがって、NSObject の mutableCopy メソッドは mutableCopyWithZone を呼び出し、その結果を返すことになると推測できます。クラスが mutableCopyWithZone メソッドを実装していない場合は、例外がスローされます。
上記のプログラムがクラッシュしたのは、mutableCopy メソッドが実装されていないためではなく、respondsToSelector によって返される結果が「不正確」であることを意味するものではなく、実際には予期されていました。