之前有沒有在大家的相互討論中,聽過“反射”這個(gè)詞币绩,而自己卻似懂非懂蜡秽?反射聽起來比較神秘,其實(shí)各位也許在自己以前的實(shí)踐中就已經(jīng)使用過了缆镣。今天就抽時(shí)間正好結(jié)合自己最近的實(shí)踐經(jīng)歷把反射整理一下芽突,希望能和大家共同交流進(jìn)步。
反射的理解
反射可以理解為類名董瞻、方法名寞蚌、屬性名等和字符串在運(yùn)行時(shí)相互轉(zhuǎn)化的一種機(jī)制田巴。
反射的原理
以執(zhí)行某個(gè)方法舉例,實(shí)質(zhì)上是發(fā)送了一個(gè)消息給Runtime挟秤,然后Runtime再根據(jù)這個(gè)Class的字符串名和這個(gè)方法的字符串名壹哺,去匹配真正相應(yīng)的方法地址,然后再執(zhí)行艘刚。同樣反射就是利用字符串去動(dòng)態(tài)的檢測(cè)管宵,從而實(shí)現(xiàn)運(yùn)行時(shí)的轉(zhuǎn)化。
常用的反射方法
常用的反射轉(zhuǎn)化方法在Foundation框架中攀甚,如下圖:
由于OC語言的動(dòng)態(tài)性,通過在運(yùn)行時(shí)調(diào)用上面API就可以實(shí)現(xiàn)相應(yīng)的反射轉(zhuǎn)化秋度。轉(zhuǎn)化之后炸庞,就需要進(jìn)一步的操作了。通過查看NSObject這個(gè)類的源碼(如下圖)荚斯,可以看出其為我們提供了一些基礎(chǔ)的方法埠居。
反射示例
自己寫了個(gè)小測(cè)試demo,可以簡單看一下使用反射的示例:
Robot.h
@interface Robot : NSObject
- (void)sayHi;
@end
Robot.m
#import "Robot.h"
@implementation Robot
- (void)sayHi {
NSLog(@"+++sayHi");
}
- (void)dance {
NSLog(@"+++dance");
}
@end
AppDelegate.m
Class robotCls = NSClassFromString(@"Robot");
if (robotCls) {
id robot1 = [[robotCls alloc] init];
SEL sel1 = NSSelectorFromString(@"sayHi");
SEL sel2 = NSSelectorFromString(@"dance");
if ([robot1 respondsToSelector:sel1]) {
[robot1 performSelector:sel1];
}
if ([robot1 respondsToSelector:sel2]) {
[robot1 performSelector:sel2];
}
}
Class carCls = NSClassFromString(@"Car");
NSLog(@"+++carCls:%@",carCls);
id car1 = [[carCls alloc] init];
NSLog(@"+++car1:%@",car1);
運(yùn)行結(jié)果如下:
反射的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 解耦合事期,消除類與類之間的依賴
缺點(diǎn)
- 代碼可讀性降低滥壕,將原有邏輯復(fù)雜化了,不利于維護(hù)
- 性能較差刑赶。(使用反射匹配字符串間接命中內(nèi)存比直接命中內(nèi)存的方式要慢捏浊。當(dāng)然懂衩,這個(gè)程度取決于使用場(chǎng)景撞叨,如果只是作為程序中很少涉及的部分,這個(gè)性能上的影響可以忽略不計(jì)浊洞。但是牵敷,如果在性能很關(guān)鍵的應(yīng)用核心邏輯中使用反射,性能問題就尤其重要了)
反射的應(yīng)用
通過運(yùn)用反射機(jī)制可以在運(yùn)行時(shí)動(dòng)態(tài)的創(chuàng)建類對(duì)象法希、調(diào)用方法或給屬性賦值枷餐、判斷類型等。在實(shí)際開發(fā)過程中如果合理運(yùn)用苫亦,能有效提高代碼的質(zhì)量毛肋,尤其是在架構(gòu)層面。
比如在最近的項(xiàng)目中屋剑,作為基礎(chǔ)的架構(gòu)SDK润匙,原本各功能模塊間相互依賴耦合,通過運(yùn)用一系列的反射機(jī)制唉匾,實(shí)現(xiàn)了各個(gè)模塊的解耦合孕讳,供上層接入方可以自主選擇性接入各個(gè)功能模塊匠楚,大大提升了接入的方便性與架構(gòu)模塊的可支配性。