筆者自語:隱隱約約的記得有次面試的時候面試官問到了:說一下oc的反射機制。我一臉懵逼的樣子,什麼是oc的反射機制呀,開發過程中聽都聽說過,怎麼說呢?相信你也遇到過類似的境況,恨不得找一個地縫鑽進去,我現在只說一句:其實就那個樣子,沒啥神祕的!
反射機制的基本概念:
找了好久oc的反射機制,只能朦朧的得到一句:跟java的反射機制相似
那麼筆者就先貼上java語言的反射機制基本概念:在執行狀態下,對於任意一個類,都能夠知道這個類的所有屬性和方法,對於任意一個物件,都能呼叫它的任意一個方法,這種動態獲取資訊,以及動態呼叫物件方法的功能叫java語言的反射機制;
那麼oc語言的反射機制與之類似是什麼樣的呢:在oc語言的反射機制跟java反射機制很相似,在oc中所有oc物件都繼承NSObject類,這個類為我們提供了基礎的方法和協議,我們可以直接呼叫這個類繼承過來的方法,這個物件的基本資訊,這大概就是oc語言的反射機制;
現在基本有了反射機制的概念,我們平時開發過程中都怎麼利用這種機制呢?
反射機制的運用
1.獲取Class物件
Class物件其實本質上是一個結構體,這個結構體的成員變數還是他自己。
typedef struct objc_class *Class;
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
}
複製程式碼
在開發過程中難免會碰到要判斷兩個物件是否同屬一個類,我們可以呼叫他們的Class方法獲取類物件比如:
// 在例項方法中通過self呼叫class例項方法獲取類物件
[self class]
// 通過ViewController類直接呼叫class類方法獲取類物件
[ViewController class]
// 在類方法中使用類物件呼叫class方法獲取類物件
+ (Class)classMethod {
return [self class];
}
複製程式碼
2.利用反射方法
系統Foundation框架為我們提供了一些方法反射的API,由於oc語言的動態性,這些操作可以發生在執行時的。
// SEL和字串轉換
FOUNDATION_EXPORT NSString *NSStringFromSelector(SEL aSelector);
FOUNDATION_EXPORT SEL NSSelectorFromString(NSString *aSelectorName);
// Class和字串轉換
FOUNDATION_EXPORT NSString *NSStringFromClass(Class aClass);
FOUNDATION_EXPORT Class __nullable NSClassFromString(NSString *aClassName);
// Protocol和字串轉換
FOUNDATION_EXPORT NSString *NSStringFromProtocol(Protocol *proto) NS_AVAILABLE(10_5, 2_0);
FOUNDATION_EXPORT Protocol * __nullable NSProtocolFromString(NSString *namestr) NS_AVAILABLE(10_5, 2_0);
複製程式碼
通過以上方法,我們可以將字串與同名的oc物件動態的相互轉化;
3.常用判斷方法
在NSObject類中我們提供一些基礎方法,用來做一些判斷操作,這些方法都是發生在執行時動態判斷的。
// 當前物件是否這個類或其子類的例項
- (BOOL)isKindOfClass:(Class)aClass;
// 當前物件是否是這個類的例項
- (BOOL)isMemberOfClass:(Class)aClass;
// 當前物件是否遵守這個協議
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
// 當前物件是否實現這個方法
- (BOOL)respondsToSelector:(SEL)aSelector;
複製程式碼
利用這些判斷方法,可以動態的判斷一個物件是否有符合一些條件;例如是否是某個類是否是某個類的例項等。