首页 > 代码库 > ios 动态执行的代码

ios 动态执行的代码

objc中可以通过动态运行的方法调用第三方库的函数

通过可以用下面的方法判断工程是否引入了第三方的库,如果引入,则可以通过NtSdkIMP获取到对应方法的函数指针去执行代码。如果没有引入,则不执行。

通过获取方法的imp指针,可以运行对应的函数,如果imp为空,说明不包含所需要的库和符号。

@interface ViewController ()@end@implementation ViewController- (int)printOneNumber:(int)number {    NSLog(@"print number %d", number);    return number + 1;}+ (NSString *)numberAddOne:(NSString *)num {    NSInteger n = [num integerValue];    n++;    NSString *ret = [NSString stringWithFormat:@"%ld", n];    NSLog(@"%@", ret);    return ret;}

如上面 ViewController 包含有

printOneNumber

numberAddOne这两个方法,

通常可以通过 int ret = [self printOneNumber:1] 调用来执行对应的函数方法也可以通过下面的imp来调用,过程比较复杂,但可以在没有声明或者引用对应头文件就可以执行对应代码

- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.        NSString *methodName = @"printOneNumber:";    IMP imp = [NtSdkIMP getInstance:self method:methodName];    int (*func)(id, SEL, ...) = (void *)imp;    if (func) {        SEL selector = NSSelectorFromString(methodName);        int ret = func(self, selector, 4);        NSLog(@"%d", ret);    }        imp = [NtSdkIMP getClass:@"ViewController" method:@"numberAddOne:"];    id (*func2)(id, SEL, ...) = (void *)imp;    if (func2) {        SEL selector = NSSelectorFromString(@"numberAddOne:");        Class classA = NSClassFromString(@"ViewController");        id s = func2(classA, selector, @"4");        NSLog(@"%@",s);            }}

如果返回的是nsobject对像,则需要用

id (*func2)(id, SEL, ...)

设定imp的格式

如果返回的是基础数据类型(非实例对象),则需要

int (*func)(id, SEL, ...)

设定imp的格式

对应的NtSdkIMP代码如下:

#import <Foundation/Foundation.h>@interface NtSdkIMP : NSObject/** *  获取类方法的函数指针 * *  @param className  对象 *  @param methodName 方法 * *  @return 函数指针 */+ (IMP)getClass:(NSString *)className method:(NSString *)methodName;/** *  获取对象方法的函数指针 * *  @param instance   对象 *  @param methodName 方法 * *  @return 函数指针 */+ (IMP)getInstance:(id)instance method:(NSString *)methodName;/** *  打印出要调用的类方法 * *  @param className  类名 *  @param methodName 方法名 *  @param arguments  参数列表 */+ (void)LogClass:(NSString *)className runMethod:(NSString *)methodName withArgs:(NSArray *)arguments;/** *  打印出要调用的对象方法 * *  @param className  类名 *  @param methodName 方法名 *  @param arguments  参数列表 */+ (void)LogInstance:(NSString *)instanceName runMethod:(NSString *)methodName withArgs:(NSArray *)arguments;@end

 

#import "NtSdkIMP.h"#import "NTLog.h"@implementation NtSdkIMP+ (IMP)getClass:(NSString *)className method:(NSString *)methodName {        Class classA = NSClassFromString(className);        //存在该类    if (classA)    {        NTLog(@"Class %@ Exist", className);        SEL selector = NSSelectorFromString(methodName);        //存在对应的方法        if ([classA respondsToSelector:selector])        {            NTLog(@"Method %@ Exist", methodName);            IMP imp = [classA methodForSelector:selector];            return imp;        }        //不存在对应的方法        else {            NTLog(@"Method NOT %@ Exist", methodName);            return NULL;        }    }    //存在该类    else {        NTLog(@"Class %@ NOT exist", className);        return NULL;    }}+ (IMP)getInstance:(id)instance method:(NSString *)methodName {        //对象存在    if (instance) {        NTLog(@"Instance %@ Exist", instance);    }    //对象不存在    else {        NTLog(@"Instance %@ NOT Exist", instance);        return NULL;    }        SEL selector = NSSelectorFromString(methodName);    //存在对应方法    if ([instance respondsToSelector:selector])    {        NTLog(@"Method %@ Exist", methodName);        IMP imp = [instance methodForSelector:selector];        return imp;    }    //不存在对应方法    else {        NTLog(@"Method %@ NOT Exist", methodName);        return NULL;    }}+ (void)LogClass:(NSString *)className runMethod:(NSString *)methodName withArgs:(NSArray *)arguments {    NTLog(@"className:%@",className);    NTLog(@"method:%@", methodName);    for (NSObject *object in arguments) {        NTLog(@"%@ %@", object.class, object);    }    //方法名队列。如果没有参数,不包括冒号,如果有多个参数,有冒号相隔,且最后一个方法名为@""    NSMutableArray *arrMethod = [NSMutableArray arrayWithArray:[methodName componentsSeparatedByString:@":"]];        //方法名不存在    if (arrMethod.count < 1) {        NTLog(@"methodname is nil");        return;    }    NSMutableString *stringMethods = [[NSMutableString alloc] init];    NSUInteger i = 0;    //不带参数    if (arrMethod.count == 1) {        [stringMethods appendString:[arrMethod firstObject]];    }    //多个参数    else {        for (NSString *method in arrMethod) {            if ([method isEqualToString:@""]) {                break;//最后一个是@"",需要去掉            }            [stringMethods appendString:method];            [stringMethods appendString:@":"];            //参数不为空对象            if ([arguments objectAtIndex:i]) {                [stringMethods appendString:[[arguments objectAtIndex:i] description]];            }            //参数是空对象            else {                [stringMethods appendString:@"nil"];            }            //加个空格            if ([arrMethod indexOfObject:method] != arrMethod.count-2) {                [stringMethods appendString:@" "];            }        }    }    //打印出要调的类方法    NTLog("\nRun Class Method: [%@ %@]", className, stringMethods);}#pragma mark TODO:+ (void)LogInstance:(id)instance runMethod:(NSString *)methodName withArgs:(NSArray *)arguments {    }@end

 

ios 动态执行的代码