iOS中的反射机制

https://github.com/starainDou 欢迎点星

iOS反射机制:运行时选择创建哪个实例,并动态选择调用哪个方法。

常用判断方法

// 当前对象是否这个类或其子类的实例
- (BOOL)isKindOfClass:(Class)aClass;
// 当前对象是否是这个类的实例
- (BOOL)isMemberOfClass:(Class)aClass;
// 当前对象是否遵守这个协议
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
// 当前对象是否实现这个方法
- (BOOL)respondsToSelector:(SEL)aSelector;

获取Class的三种方法

// 通过字符串获取class  
Class class = NSClassFromString(@"NSString");  
NSLog(@"class type : %@", class);  

// 直接用class 来创建对象 ,通过对象来获取class 
id str = [[class alloc] init];   
NSLog(@"%@", [str class]);  

// 通过类来获取class  
NSLog(@"%d", class==NSString.class);   

实际应用

根据后台推送过来的数据,进行动态页面跳转,跳转到页面后根据返回到数据执行对应的操作。

如果采用传统方法,需要引入很多头文件,并且需要作很多判断if..else..(或switch)。如果需求又添加新的,那么...GG

#import "JumpManager.h"
#import "MeViewController.h"
#import "MessageViewController.h"
#import "BusinessViewController.h"
#import "bookViewController.h"
......

@implementation JumpManager

+ (void)jumpWithMessage:(PushMessage *)message navController:(UINavigationController *)navController  {
    if(message.type == T1) {
        xxx
    } else if(message.type == T2) {
        xxx
    } else if(message.type == T3) {
        xxx
    } 
        ......
        
    } else {
        xxx
    }
}
 
@end

这种情况反射机制就派上用场了,我们可以用反射机制动态的创建类并执行方法。当然也可以通过runtime来实现这个功能,但是我们当前需求反射机制已经足够满足需求了,如果遇到更加复杂的需求可以考虑用runtime来实现。

这时候就需要和后台配合了,我们首先需要和后台商量好返回的数据结构,以及数据格式、类型等,返回后我们按照和后台约定的格式,根据后台返回的信息,直接进行反射和调用即可。

{
     "className" : "MessageViewController", 
    "method" : "refresh",
    "properties" : {
                        "msgId": 1223030330, 
                        "msgType": 3
                    }
};

className就是跳转目标界面的类名,method就是类的实例方法,properties为实例方法调用所需的参数。

#import "JumpManager.h"

@implementation JumpManager

+ (void)jumpWithDict:(NSDictionary *)dict navController:(UINavigationController *)navController
{
    Class class = NSClassFromString(dict[@"className"]);
    UIViewController *vc = [[class alloc] init];
    NSDictionary *properties = dict[@"properties"];
    [properties enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        // 如果没有这个字段或obj为nil,让它报错好了,这样就知道问题出在哪了
        [vc setValue:obj forKey:key];
    }];
    SEL selector = NSSelectorFromString(dict[@"method"]);
    [vc performSelector:selector];
    [navController pushViewController:vc animated:YES];
}
 
@end
  • OC中使用反射的优点

松耦合,类与类之间不需要太多依赖
构建灵活

  • OC中使用反射的缺点

不利于维护。使用反射模糊了程序内部实际发生的事情,隐藏了程序的逻辑。这种绕过源码的方式比直接代码更为复杂,增加了维护成本。

性能较差。使用反射匹配字符串间接命中内存比直接命中内存的方式要慢。当然,这个程度取决于使用场景,如果只是作为程序中很少涉及的部分,这个性能上的影响可以忽略不计。但是,如果在性能很关键的应用核心逻辑中使用反射,性能问题就尤其重要了

Objective-C 反射机制
反射机制及其在iOS中的应用

你可能感兴趣的:(iOS中的反射机制)