首先,我的理解是:
(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의 하위 클래스이므로 responseToSelector가 true를 반환하는 데 문제가 없습니다. responseToSelector는 단순히 메소드 이름만 확인하는 것이 아니라, 메소드 선언은 있지만 구현은 없어도 상관없습니다. 반드시 구현해야 하는 요구 사항입니다. NSObject 클래스에는 설명서에 명시된 대로 mutableCopy 메서드가 구현되어 있습니다.
에 대한 구현이 없습니다.mutableCopyWithZone에서 반환된 개체를 반환합니다.
이는 NSMutableCopying 프로토콜을 채택하는 클래스에 대한 편의 메서드입니다. mutableCopyWithZone:.
따라서 NSObject의 mutableCopy 메서드는 mutableCopyWithZone을 호출하고 결과를 반환하는 것이라고 추측할 수 있습니다. 클래스가 mutableCopyWithZone 메서드를 구현하지 않으면 예외가 발생합니다.
위 프로그램이 충돌한 이유는 mutableCopy 메서드가 구현되지 않았기 때문도 아니고,responsToSelector에서 반환된 결과가 실제로 예상했던 결과였기 때문도 아닙니다.