對象在運行時獲取其類型的能力稱為內(nèi)省陷谱。內(nèi)省可以有多種方法實現(xiàn)烙博。
OC運行時內(nèi)省的4個方法:
判斷對象類型:
-(BOOL) isKindOfClass: 判斷是否是這個類或者這個類的子類的實例
-(BOOL) isMemberOfClass: 判斷是否是這個類的實例
判斷對象or類是否有這個方法
-(BOOL) respondsToSelector: 判讀實例是否有這樣方法
+(BOOL) instancesRespondToSelector: 判斷類是否有這個方法
在 Objective-C 中瑟蜈,id類型類似于(void*) ,可以指向任何類的對象渣窜,但在運行時對象的類型不再是id铺根,而是該對象真正所屬的類。
Person *person = [[Person alloc] init];
NSArray *arr = @[person];
id obj = arr[0]; //OC集合中取出的對象都是id類型
此時可通過
BOOL isPersonClass = [obj isKindOfClass: [Person class] ];
來判斷obj是否Person類型或其子類的對象乔宿。
在 Objective-C 中位迂,用父類類型定義的指針,可以指向其子類的對象详瑞,但在運行時對象真實類型會是子類掂林。
//例如 Boy是Person的子類,現(xiàn)定義:
Person *p = [[Boy alloc] init];
可通過 BOOL isBoy = [p isMemberOfClass: [Boy class] ];
判斷Person *類型的p是否是Boy類型坝橡。
在使用代理調(diào)用代理方法時泻帮,并不知道代理對象有沒有實現(xiàn)對應方法,如未實現(xiàn)就會報方法找不到的錯誤计寇。此時最好使用respondsToSelector:先判斷下锣杂,然后調(diào)用會比較安全。
另外番宁,可以用來判斷方法的版本元莫,避免找不到方法報錯。
例如:iOS8以后UIApplication新增注冊遠程通知的方法贝淤,如果ios7及以下系統(tǒng)中調(diào)用[application registerForRemoteNotifications];立即會崩潰柒竞。
@interface UIApplication (UIRemoteNotifications)
- (void)registerForRemoteNotifications NS_AVAILABLE_IOS(8_0);
@end
此時可以用respondsToSelector來判斷:
if ([application respondsToSelector:@selector(registeredForRemoteNotifications)])
{ //IOS8
[application registerForRemoteNotifications];
}
else { // ios7
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
//夾在3個#pragma中間的不報方法過期警告
[application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
#pragma clang diagnostic pop
}
/*
如果不知道某個方法在哪個版本出現(xiàn)的,就可以用respondsToSelector來判斷以避免崩潰播聪。
當然也可以先判斷[UIDevice currentDevice].systemVersion.floatValue >= 8.0,
再調(diào)用registerForRemoteNotifications方法布隔。
*/