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

首先,我的理解是:
(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

学习是最好的投资!

membalas semua(1)
大家讲道理

conformsToProtocol adalah untuk mengesan sama ada kelas mematuhi protokol tertentu Ia tidak ada kaitan dengan sama ada kelas melaksanakan kaedah protokol (sudah tentu, kaedah yang diisytiharkan diperlukan dalam protokol mesti dilaksanakan).

respondsToSelector adalah untuk mengesan sama ada kelas atau kelas induknya boleh membalas mesej tertentu. Dalam contoh anda, NSObject boleh bertindak balas kepada mesej mutableCopy, dan NSNumber ialah subkelas NSObject, jadi tiada masalah dengan respondsToSelector mengembalikan benar. respondsToSelector tidak hanya menyemak nama kaedah, tidak kira jika terdapat pengisytiharan kaedah tetapi tiada pelaksanaan. Ia adalah satu keperluan yang mesti dilaksanakan. Kelas NSObject mempunyai pelaksanaan kaedah mutableCopy, seperti yang dinyatakan dalam dokumentasi:
Mengembalikan objek yang dikembalikan oleh mutableCopyWithZone:.
Ini ialah kaedah mudah untuk kelas yang menggunakan protokol NSMutableCopying Pengecualian dibangkitkan jika ada tiada pelaksanaan untuk mutableCopyWithZone:.

Jadi kita boleh meneka bahawa kaedah mutableCopy NSObject adalah untuk memanggil mutableCopyWithZone dan mengembalikan hasilnya Jika kelas tidak melaksanakan kaedah mutableCopyWithZone, pengecualian akan dilemparkan.

Program anda di atas ranap bukan kerana kaedah mutableCopy tidak dilaksanakan, dan tidak bermakna hasil yang dikembalikan oleh respondsToSelector adalah "tidak tepat".

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan