ios - respondsToSelector: 和 conformsToProtocol:的区别
PHPz
PHPz 2017-04-17 17:46:29
0
1
549

首先,我的理解是:
(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:方法没有实现;

PHPz
PHPz

学习是最好的投资!

全部回覆(1)
大家讲道理

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 返回的結果“不准確“,其實是在意料之內的。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板