iOS热修复之LYFix(基于aspects)
点击上方“iOS开发”,选择“置顶公众号”
关键时刻,第一时间送达!
作者:iOS开发Go
链接:https://www.jianshu.com/p/2fd3018955e2
iOS开发整理发布,转载请联系作者获得授权
简介
LYFix Demo
LYFix 基于 Aspects (做了一点改动),NSInvocation实现的简单hotfix方案。
LYFix 通过下发js代码提供以下功能:
在任意方法前后加入代码 (基于aspects)。
替换任意方法的实现 (基于aspects)。
调用任意方法 (基于NSInvocation)。
修改方法参数 (基于NSInvocation)。
修改方法返回值 (基于NSInvocation)。
使用
1. 初始化
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[LYFix Fix];
return YES;
}
使用的aspects的枚举
typedef NS_OPTIONS(NSUInteger, AspectOptions) {
AspectPositionAfter = 0, /// Called after the original implementation (default)
AspectPositionInstead = 1, /// Will replace the original implementation.
AspectPositionBefore = 2, /// Called before the original implementation.
AspectOptionAutomaticRemoval = 1 < < 3 /// Will remove the hook after the first execution.
};
2.方法前插入代码
fixMethod('Test', 'runBeforeInstanceMethod', 2,
function(){
runMethod('Test', 'log');
});
3.方法后插入代码
fixMethod('Test', 'runAfterInstanceMethod', 0,
function(){
runMethod('Test', 'log');
});
4.替换方法
fixMethod('Test', 'runInsteadClassMethod', 1,
function(){
runMethod('Test', 'log');
});
5.修复方法
fixMethod('Test', 'instanceMethodCrash:', 1,
function(instance, originInvocation, originArguments) {
if (originArguments[0] == null) {
runError('Test', 'instanceMethodCrash');
} else {
runInvocation(originInvocation);
}
});
6.修改参数
fixMethod('Test','runWithParams:',1,function(instance,invocation,arg){
var array = new Array('123');
var arr = new Array(array);
setInvocationArguments(invocation,arr);
runInvocation(invocation);
});
7.修改返回值
fixMethod("Test", "changeReturnValue:", 1, function(instance, invocation, arg) {
runInvocation(invocation);
setInvocationReturnValue(invocation,'new returnValue');
});
源码
初始化方法,有其他方法供js调用还可以在此继续添加。
+ (void)Fix {
JSContext *context = [self context];
context[@"fixMethod"] = ^(NSString *className, NSString *selectorName, AspectOptions options, JSValue *fixImp) {
[self fixWithClassName:className opthios:options selector:selectorName fixImp:fixImp];
};
context[@"runMethod"] = ^id(NSString * className, NSString *selectorName, id arguments) {
id obj = [self runWithClassname:className selector:selectorName arguments:arguments];
return obj;
};
context[@"runInstanceMethod"] = ^id(id instance, NSString *selectorName, id arguments) {
id obj = [self runWithInstance:instance selector:selectorName arguments:arguments];
return obj;
};
context[@"runClassMethod"] = ^id(NSString * className, NSString *selectorName, id arguments) {
id obj = [self runWithClassname:className selector:selectorName arguments:arguments];
return obj;
};
context[@"runInvocation"] = ^(NSInvocation *invocation) {
[invocation invoke];
};
context[@"setInvocationArguments"] = ^(NSInvocation *invocation, id arguments) {
if ([arguments isKindOfClass:NSArray.class]) {
invocation.arguments = arguments;
} else {
[invocation setMyArgument:arguments atIndex:0];
}
};
context[@"setInvocationArgumentAtIndex"] = ^(NSInvocation *invocation, id argument,NSInteger index) {
[invocation setMyArgument:argument atIndex:index];
};
context[@"setInvocationReturnValue"] = ^(NSInvocation *invocation, id returnValue) {
invocation.returnValue_obj = returnValue;
};
context[@"runError"] = ^(NSString *instanceName, NSString *selectorName) {
NSLog(@"runError: instanceName = %@, selectorName = %@", instanceName, selectorName);
};
context[@"runLog"] = ^(id logs) {
NSLog(@"xly--%@",logs);
};
}
基于aspects前插、后插、替换
+ (void)fixWithClassName:(NSString *)className opthios:(AspectOptions)options selector:(NSString *)selector fixImp:(JSValue *)fixImp {
Class cla = NSClassFromString(className);
SEL sel = NSSelectorFromString(selector);
if ([cla instancesRespondToSelector:sel]) {
} else if ([cla respondsToSelector:sel]){
cla = object_getClass(cla);
} else {
return;
}
[cla aspect_hookSelector:sel withOptions:options usingBlock:^(id aspectInfo) {
[fixImp callWithArguments:@[aspectInfo.instance, aspectInfo.originalInvocation, aspectInfo.arguments]];
} error:nil];
}
基于NSInvocation方法调用
+ (id)runWithInstance:(id)instance selector:(NSString *)selector arguments:(NSArray *)arguments {
if (!instance) {
return nil;
}
SEL sel = NSSelectorFromString(selector);
NSLog(@"xly--%@",[instance class]);
if ([instance isKindOfClass:JSValue.class]) {
instance = [instance toObject];
}
NSMethodSignature *signature = [instance methodSignatureForSelector:sel];
if (!signature) {
return nil;
}
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.selector = sel;
invocation.arguments = arguments;
[invocation invokeWithTarget:instance];
return invocation.returnValue_obj;
}
+ (id)runWithClassname:(NSString *)className selector:(NSString *)selector arguments:(NSArray *)arguments {
Class cla = NSClassFromString(className);
SEL sel = NSSelectorFromString(selector);
if ([cla instancesRespondToSelector:sel]) {
id instance = [[cla alloc] init];
NSMethodSignature *signature = [instance methodSignatureForSelector:sel];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.selector = sel;
invocation.arguments = arguments;
[invocation invokeWithTarget:instance];
return invocation.returnValue_obj;
} else if ([cla respondsToSelector:sel]){
NSMethodSignature *signature = [cla methodSignatureForSelector:sel];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.selector = sel;
invocation.arguments = arguments;
[invocation invokeWithTarget:cla];
return invocation.returnValue_obj;
} else {
return nil;
}
}
NSInvocation拓展(提供修改参数,返回值等)
▼点击「阅读原文」进入程序员商城
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

随时掌握互联网精彩
赞助链接
排名
热点
搜索指数
- 1 习近平的科技情怀 7998940
- 2 湖北省委原书记蒋超良被查 7904418
- 3 《哪吒2》大爆之后最令人担忧的事 7881343
- 4 创新服务“换”出消费新活力 7783584
- 5 DeepSeek回答彩礼该给多少 7620754
- 6 蒋超良被查 湖北省委表态 7551631
- 7 《哪吒2》票房破130亿 7496856
- 8 有骑手试水京东外卖 日入500元 7366397
- 9 奶奶每天玩手机到凌晨近视2300度 7238199
- 10 民警建议家里不要安装摄像头 7178930