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