二、ObjC的反射机制

反射是指程序在运行时可以访问、检测和修改程序本身的状态或行为的一种能力,OC是基于Runtime运行时系统的动态语言,具有强大的反射能力。OC的反射机制通常是指NSFoundation中为反射功能提供的一系列API,它们是基于Runtime的封装,是Runtime编程的子集。

1. 获取对象类型

NSFoundation的根类NSObject中实现了-class方法,默认情况下它返回的是isa指向的类,但它可以被子类重写(比如KVO中),造成此方法返回的类和isa指向的类不一致的情况;Runtime提供了Class object_getClass(id obj)函数来获取对象所属的类,此函数直接返回对象isa所指向的类;NSFoundation中还提供了类方法+class,该方法返回的就是当前类,而不是类的类(元类)。

2. 对象检测方法

NSFoundation中根类NSObject实现了一系列方法,来对对象的类型、协议、方法等做检测判断:

1
2
3
4
5
6
7
8
9
10
// @protocol NSObject
- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
- (BOOL)respondsToSelector:(SEL)aSelector;

// @interface NSObject
+ (BOOL)instancesRespondToSelector:(SEL)aSelector;
+ (BOOL)conformsToProtocol:(Protocol *)protocol;
+ (BOOL)isSubclassOfClass:(Class)aClass;

3.消息派发

NSFoundation中根类NSObject实现一系列Perform Selector,它们有的是对objc_msgSend的封装,有的则是基于线程的RunLoop来实现的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// @protocol NSObject
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

// @interface NSObject (NSDelayedPerforming)
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSRunLoopMode> *)modes;
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;

// @interface NSObject (NSThreadPerformAdditions)
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg;

Perform Selector中有返回值的API要注意返回的对象可能会内存泄露,进行延迟派发、派发给其他线程、以及当前线程异步派发时,要注意判断目标线程的RunLoop是否运行。

4. 反射方法

NSFoundation中还提供了字符串和Selector、类、协议互相装换的API,以方便放射功能的使用:

1
2
3
4
5
6
7
8
NSString *NSStringFromSelector(SEL aSelector);
SEL NSSelectorFromString(NSString *aSelectorName);

NSString *NSStringFromClass(Class aClass);
Class __nullable NSClassFromString(NSString *aClassName);

NSString *NSStringFromProtocol(Protocol *proto);
Protocol * __nullable NSProtocolFromString(NSString *namestr);
-------------This article is over, thank you for reading -------------