看了一下网上对Aspects做热修复的代码,代码是用不了的,所以有兴趣看了一下,并且做了一定的修改
用到的知识
- JavaScriptCore
- Aspects
- runtime message
热修复
先说说热修复,前人已经对这里描述的挺清楚了,这里引用一下
热更新
原文里面的
[self context][@"runClassWith2Paramters"] = ^id(NSString *className, NSString *selectorName, id obj1, id obj2) {
return [self _runClassWithClassName:className selector:selectorName obj1:obj1 obj2:obj2];
};
这种方法传参传了id,不知道是怎么做到的,于是自己做了一定的修改,把id obj改为了json字符串,自定义了使用的方法,在传参方面增加了基础参数的添加方法,在代码结构里面添加了几个demo,欢迎食用。
主要方法
+ (void)_runInstanceWithInstance:(NSString *)instanceName keyPath:(NSString *)keyPath selector:(NSString *)selector parameter1:(NSString *)parameter1 parameter2:(NSString *)parameter2 {
/*
HotFixManager 是作为存储实例的一个单例,如果跑实例方法却又重新alloc init的话,
在当前页面上就无法展示了,具体可以查看demo
*/
//搜索当前实例是否存在,如果存在的话继续
id instance = [[HotFixManager shareManager] ViewController];
if (!instance) {
NSLog(@"对象未找到");
return ;
}
if (keyPath) {
instance = [instance valueForKeyPath:keyPath];
}
// 1.通过方法调用者创建方法签名;此方法是NSObject 的方法
NSMethodSignature *sig = [[instance class] instanceMethodSignatureForSelector:NSSelectorFromString(selector)];
// 2.通过方法签名 生成NSInvocation
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
invocation.target = instance;
invocation.selector = NSSelectorFromString(selector);
// 注意 参数必须从2开始 因为0跟1已经被self,_cmd占用了
// 3.对parameter进行操作
if(parameter1) {
id obj1 = [self fixObject:[self transferDictionary:parameter1]];
[invocation setArgument:&obj1 atIndex:2];
}
if (parameter2) {
id obj2 = [self fixObject:[self transferDictionary:parameter2]];
[invocation setArgument:&obj2 atIndex:3];
}
//执行invoke
[invocation invoke];
}
获取参数的方法
@interface ParamsHandler : NSObject
/** 字典处理 */
- initWithDictionary:(NSDictionary *)dic;
/** 处理JS返回回来的Json字符串,返回基本对象 */
- (id)fixIt;
@property (nonatomic, strong) NSString *type;
@property (nonatomic, strong) NSString *cls;
@property (nonatomic, strong) NSString *selector;
@property (nonatomic, strong) NSArray *parameters;
@property (nonatomic, strong) NSString *keyPath;
@end
- (id)fixIt {
NSObject *obj;
if ([self.type isEqualToString:@"instance"]) { //实例方法,将JS传过来的json字符串转化为iOS对象
Class class = NSClassFromString(self.cls);
// 这里就仅限传两个参数,主要是比较懒,有需要的同学自己添加两个以上的吧
if (_parameters.count == 0) {
obj = ((NSObject* (*) (id,SEL)) objc_msgSend) ([class alloc],sel_registerName(self.selector.UTF8String));
} else if (_parameters.count == 1) {
obj = ((NSObject* (*) (id,SEL,NSObject *)) objc_msgSend) ([class alloc],sel_registerName(self.selector.UTF8String),_parameters[0]);
} else if (_parameters.count == 2) {
obj = ((NSObject* (*) (id,SEL,NSObject *,NSObject *)) objc_msgSend) ([class alloc],sel_registerName(self.selector.UTF8String),_parameters[0],_parameters[1]);
}
} else if ([self.type isEqualToString:@"class"]) { // 类方法
Class class = NSClassFromString(self.cls);
if (_parameters.count == 0) {
obj = ((NSObject* (*) (id,SEL)) objc_msgSend) (class,sel_registerName(self.selector.UTF8String));
} else if (_parameters.count == 1) {
obj = ((NSObject* (*) (id,SEL,NSObject *)) objc_msgSend) (class,sel_registerName(self.selector.UTF8String),_parameters[0]);
} if (_parameters.count == 2) {
obj = ((NSObject* (*) (id,SEL,NSObject *,NSObject *)) objc_msgSend) (class ,sel_registerName(self.selector.UTF8String),_parameters[0],_parameters[1]);
}
}
return obj;
}
网友评论