IOS 使用反射进行游戏聚合多渠道

通过传入的字符串来获取类名和函数名调用相应的函数,这样做又一个好处是可以不导入相应的文件,而且完成编译

//调用类函数
Class cls = NSClassFromString(@"John");
    SEL sel0 = NSSelectorFromString(@"showDefaultMsg");
    if ([cls respondsToSelector:sel0]) {
        [cls performSelector:sel0];
    }

   //通过实例调用函数 
    id obj = [[cls alloc]init];
    //函数字符串一定不要有空格
    SEL selector = NSSelectorFromString(@"show:Num:");
    if ([obj respondsToSelector:selector]) {
        //目前只能实现两个参数
        [obj performSelector:selector withObject:@"Hehe" withObject:@123];
    }

但是有个问题 performSelector 最多传递两个参数,当然如果这个函数是我们自己定义的可以通过使用NSDictionary 和NSArray实现多参数传递,大部分是我们调用别人编写的函数,这样我们只能使用runtime消息机制了

//调用这个带回调的函数
-(NSInteger)getDataWithParms:(NSDictionary*)dic Completion:(void(^)(NSDictionary*dic,int ret,BOOL issuccess))complete;

//
 Class cls = NSClassFromString(@"John");
 id obj = [[cls alloc]init];
 //(void(^)(NSDictionary*dic,int ret,BOOL issuccess))complete;
 //block 参数定义->返回值类型 (^变量名)(参数列表) = Block表达式

void (^block)(NSDictionary*dic,int ret,BOOL issuccess) = ^(NSDictionary*dic,int ret,BOOL issuccess){
        NSLog(@"%@,%d,%@",dic,ret,issuccess?@"成功":@"失败");
    //SEL 参数,
    SEL sel4 = NSSelectorFromString(@"getDataWithParms:Completion:");
    //反射判断函数是否存在
    if ([obj respondsToSelector:sel4]) {
        NSDictionary*dic = @{@"Hello":@"My",@"friend":@"John",@"haha":@"keyile"};
       NSInteger sdd =  ((NSInteger(*)(id,SEL,NSDictionary*,id))objc_msgSend)(obj,sel4,dic,block);
        NSLog(@"%ld",(long)sdd);
    }

-(void)test2:(NSString*)str Num:(NSNumber*)num Arr:(NSArray*)arr;
//NSInter 或者 Int 类型注意,objc_msgSend 我无法使用传递值类型, 使用NSNumber 传递
    SEL sel2 = NSSelectorFromString(@"test2:Num:Arr:");
    if ([obj respondsToSelector:sel2]) {
        //传多参
        ((void (*) (id, SEL,NSString*,NSNumber*,NSArray*)) objc_msgSend) (obj, sel_registerName("test2:Num:Arr:"),@"Hello msg_Send",@123,@[@1,@"12"]);
    }

现在写了一个调用实例
ReflectionObj.h

#import <Foundation/Foundation.h>

@interface ReflectionObj : NSObject
+(instancetype)sharedInstance;

+(Class)getClasFromStr:(NSString*)clsName;

/*带返回值的反射函数,如果没返回值调用会导致崩溃
 *objc 如果类函数就是类名或实体对象,实体函数就是实体对象
 *AndSelName 函数名 例:-(NSString*)fun:(int)x; 就传入:@“fun:”
 *AndParms 就是对应的参数
 *返回值对象类型
 */
+(instancetype)perferFunWithReturn:(id)objc AndSelName:(NSString*)selname AndParms:(NSArray*)parms;

/*不带返回值的反射函数,如果有返回值调用会无法获取返回值
 *objc 如果类函数就是类名或实体对象,实体函数就是实体对象
 *AndSelName 函数名 例:-(NSString*)fun:(int)x; 就传入:@“fun:”
 *AndParms 就是对应的参数
 *无返回值
 */
+(void)perferFunWithObj:(id)objc AndSelName:(NSString*)selname AndParms:(NSArray*)parms;
@end

ReflectionObj.m

//
//  ReflectionObj.m
//
//  Created by syStudio sy on 2018/8/15.
//  Copyright © 2018年 syStudio sy. All rights reserved.
//

#import "ReflectionObj.h"
#import <objc/runtime.h>
#import <objc/message.h>
@implementation ReflectionObj
+(instancetype)sharedInstance{
    static ReflectionObj *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[ReflectionObj alloc]init];
    });
    return instance;
}

+(Class)getClasFromStr:(NSString*)clsName{
    return NSClassFromString(clsName);
}
+(void)perferFunWithObj:(id)objc AndSelName:(NSString*)selname AndParms:(NSArray*)parms{
    SEL sel = NSSelectorFromString(selname);
    if (parms.count==0) {
        if ([objc respondsToSelector:sel]) {
              ((id (*) (id, SEL)) objc_msgSend) (objc, sel_registerName(selname.UTF8String));
        }
    }else if(parms.count==1){
        if ([objc respondsToSelector:sel]) {
              ((id (*) (id, SEL,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0]);
        }

    }else if(parms.count==2){
        if ([objc respondsToSelector:sel]) {
              ((id (*) (id, SEL,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1]);
        }

    }else if(parms.count==3){
        if ([objc respondsToSelector:sel]) {
               ((id (*) (id, SEL,id,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1],[parms objectAtIndex:2]);
        }
    }else if(parms.count==4){
        if ([objc respondsToSelector:sel]) {
              ((id (*) (id, SEL,id,id,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1],[parms objectAtIndex:2],[parms objectAtIndex:3]);
        }
    }else if(parms.count==5){
        if ([objc respondsToSelector:sel]) {
             ((id (*) (id, SEL,id,id,id,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1],[parms objectAtIndex:2],[parms objectAtIndex:3],[parms objectAtIndex:4]);
        }
    }else if(parms.count==6){
        if ([objc respondsToSelector:sel]) {
              ((id (*) (id, SEL,id,id,id,id,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1],[parms objectAtIndex:2],[parms objectAtIndex:3],[parms objectAtIndex:4],[parms objectAtIndex:5]);
        }
    }else{
        if ([objc respondsToSelector:sel]) {
              ((id (*) (id, SEL,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1]);
        }

    }
    return ;
}
+(instancetype)perferFunWithReturn:(id)objc AndSelName:(NSString*)selname AndParms:(NSArray*)parms{
    SEL sel = NSSelectorFromString(selname);
    if (parms.count==0) {
        if ([objc respondsToSelector:sel]) {
            return  ((id (*) (id, SEL)) objc_msgSend) (objc, sel_registerName(selname.UTF8String));
        }
    }else if(parms.count==1){
        if ([objc respondsToSelector:sel]) {
            return  ((id (*) (id, SEL,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0]);
        }

    }else if(parms.count==2){
        if ([objc respondsToSelector:sel]) {
            return   ((id (*) (id, SEL,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1]);
        }

    }else if(parms.count==3){
        if ([objc respondsToSelector:sel]) {
            return   ((id (*) (id, SEL,id,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1],[parms objectAtIndex:2]);
        }
    }else if(parms.count==4){
        if ([objc respondsToSelector:sel]) {
            return   ((id (*) (id, SEL,id,id,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1],[parms objectAtIndex:2],[parms objectAtIndex:3]);
        }
    }else if(parms.count==5){
        if ([objc respondsToSelector:sel]) {
            return   ((id (*) (id, SEL,id,id,id,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1],[parms objectAtIndex:2],[parms objectAtIndex:3],[parms objectAtIndex:4]);
        }
    }else if(parms.count==6){
        if ([objc respondsToSelector:sel]) {
            return   ((id (*) (id, SEL,id,id,id,id,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1],[parms objectAtIndex:2],[parms objectAtIndex:3],[parms objectAtIndex:4],[parms objectAtIndex:5]);
        }
    }else{
        if ([objc respondsToSelector:sel]) {
            return   ((id (*) (id, SEL,id,id)) objc_msgSend) (objc, sel_registerName(selname.UTF8String),[parms objectAtIndex:0],[parms objectAtIndex:1]);
        }
        return NULL;
    }
    return NULL;
}

@end

使用的时候可以修改配置文件方式,通过反射找到对应的类,然后调用不同渠道,实现聚合,这一种比给项目添加多个Target 还是有优势的
gameJson.string

{
    "sdk_type": "JuHeSDK",
    "sdk_version": "1.0.0",
    "sdk_url": "http:x x x x x",
    "channel_id": "1",
    "channel_name": "Base",
    "channel_params": {
        "sdk_game": "xxxx",
        "sdk_key": "xxxxxxxxxxxxxxxxxxx"
    }
}

SyJhJsonModel.h文件

//读取配置文件类
@interface SyJhJsonModel : NSObject
@property(nonatomic,strong,readonly)NSString*sdk_type;
@property(nonatomic,strong,readonly)NSString*sdk_version;
@property(nonatomic,strong,readonly)NSString*sdk_url;
@property(nonatomic,strong,readonly)NSString*channel_id;
@property(nonatomic,strong,readonly)NSString*channel_name;
@property(nonatomic,strong,readonly)NSDictionary*channel_params;
+(SyJhJsonModel*)sharedInstance;
@end

SyJhJsonModel.m文件

#import "SyJhJsonModel.h"
@implementation SyJhJsonModel
static SyJhJsonModel *instance = nil;
+(SyJhJsonModel*)sharedInstance{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc]init];
    });
    return instance;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
    });
    return instance;
}
-(instancetype)init{
    if (self=[super init]) {
        [self loadData];
    }
    return self;
}
//加载配置文件
-(void)loadData{
    NSString* path = [[NSBundle mainBundle] pathForResource: @"gameJson" ofType: @"json"];
   NSString*jsonStr  = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil] ;
    if (jsonStr.length==0) {
        return;
    }
    NSError *err;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:[jsonStr dataUsingEncoding:NSUTF8StringEncoding]
                                                        options:NSJSONReadingMutableContainers
                                                          error:&err];
    if (err) {
        return;
    }
    for (NSString*key in dic.allKeys) {
        [self setValue:dic[key] forKey:key];
    }
}

@end

游戏渠道相关
参考文章
欢迎进入QQ群技术交流:476323497

猜你喜欢

转载自blog.csdn.net/bobbob32/article/details/81868823