筆者自語:隱隱約約的記得有次面試的時候面試官問到了:說一下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;
利用這些判斷方法,可以動態的判斷一個對象是否有符合一些條件;例如是否是某個類是否是某個類的實例等。