Skip to content

Commit 5217089

Browse files
committed
修复 OCRunner 与 Aspects 等 Swizzle 库一起使用时,补丁方法获取参数/返回值异常的问题
1 parent da0f36f commit 5217089

File tree

4 files changed

+46
-11
lines changed

4 files changed

+46
-11
lines changed

OCRunner/ORCoreImp/ORCoreImp.m

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ void methodIMP(ffi_cif *cfi,void *ret,void **args, void*userdata){
3030
__unsafe_unretained id target = *(__unsafe_unretained id *)args[0];
3131
SEL sel = *(SEL *)args[1];
3232
BOOL classMethod = object_isClass(target);
33-
NSMethodSignature *sig = [target methodSignatureForSelector:sel];
34-
NSMutableArray<MFValue *> *argValues = [NSMutableArray array];
35-
for (NSUInteger i = 2; i < sig.numberOfArguments; i++) {
36-
MFValue *argValue = [[MFValue alloc] initTypeEncode:[sig getArgumentTypeAtIndex:i] pointer:args[i]];
33+
NSArray<ORTypeVarPair *> *paramTypes = methodImp.declare.parameterTypes;
34+
FATAL_CHECK(cfi->nargs == 2 + paramTypes.count, @"ffi_cif nargs mismatch with parameterTypes");
35+
NSMutableArray<MFValue *> *argValues = [NSMutableArray arrayWithCapacity:paramTypes.count];
36+
for (NSUInteger i = 0; i < paramTypes.count; i++) {
37+
MFValue *argValue = [[MFValue alloc] initTypeEncode:paramTypes[i].typeEncode pointer:args[i + 2]];
3738
//针对系统传入的block,检查一次签名,如果没有,将在结构体中添加签名信息.
3839
if (argValue.isObject && argValue.isBlockValue && argValue.objectValue != nil) {
3940
struct MFSimulateBlock *bb = (void *)argValue->realBaseValue.pointerValue;
@@ -43,7 +44,7 @@ void methodIMP(ffi_cif *cfi,void *ret,void **args, void*userdata){
4344
argValue.pointer = &copied;
4445
}
4546
if (NSBlockHasSignature(argValue.objectValue) == NO) {
46-
ORTypeVarPair *blockdecl = methodImp.declare.parameterTypes[i - 2];
47+
ORTypeVarPair *blockdecl = paramTypes[i];
4748
if ([blockdecl.var isKindOfClass:[ORFuncVariable class]]) {
4849
NSBlockSetSignature(argValue.objectValue, blockdecl.blockSignature);
4950
}
@@ -67,7 +68,7 @@ void methodIMP(ffi_cif *cfi,void *ret,void **args, void*userdata){
6768
returnValue = [methodImp execute:scope];
6869
if (returnValue.type != TypeVoid && returnValue.pointer != NULL){
6970
// 类型转换
70-
[returnValue writePointer:ret typeEncode:[sig methodReturnType]];
71+
[returnValue writePointer:ret typeEncode:methodImp.declare.returnType.typeEncode];
7172
}
7273

7374
if (ctx.isDeallocScope) {
@@ -112,22 +113,20 @@ void getterImp(ffi_cif *cfi,void *ret,void **args, void*userdata){
112113
SEL sel = *(SEL *)args[1];
113114
ORPropertyDeclare *propDef = (__bridge ORPropertyDeclare *)userdata;
114115
NSString *propName = propDef.var.var.varname;
115-
NSMethodSignature *sig = [target methodSignatureForSelector:sel];
116116
__autoreleasing MFValue *propValue = objc_getAssociatedObject(target, mf_propKey(propName));
117117
if (!propValue) {
118118
propValue = [MFValue defaultValueWithTypeEncoding:propDef.var.typeEncode];
119119
}
120120
if (propValue.type != TypeVoid && propValue.pointer != NULL){
121-
[propValue writePointer:ret typeEncode:sig.methodReturnType];
121+
[propValue writePointer:ret typeEncode:propDef.var.typeEncode];
122122
}
123123
}
124124

125125
void setterImp(ffi_cif *cfi,void *ret,void **args, void*userdata){
126126
id target = *(__strong id *)args[0];
127-
SEL sel = *(SEL *)args[1];
128-
const char *argTypeEncode = [[target methodSignatureForSelector:sel] getArgumentTypeAtIndex:2];
129-
MFValue *value = [MFValue valueWithTypeEncode:argTypeEncode pointer:args[2]];
130127
ORPropertyDeclare *propDef = (__bridge ORPropertyDeclare *)userdata;
128+
const char *argTypeEncode = propDef.var.typeEncode;
129+
MFValue *value = [MFValue valueWithTypeEncode:argTypeEncode pointer:args[2]];
131130
NSString *propName = propDef.var.var.varname;
132131
MFPropertyModifier modifier = propDef.modifier;
133132
if (modifier & MFPropertyModifierMemWeak) {

OCRunnerDemo/OCRunnerDemo/HotPath/ViewController1.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ - (void)pushSwiftControlelr1{
132132
[self.navigationController pushViewController:vc animated:YES];
133133
}
134134

135+
- (void)buttonAction:(UIButton *)sender
136+
{
137+
NSLog(@"buttonAction hotfix, sender: %@", sender);
138+
[self ORGbuttonAction:sender];
139+
}
140+
135141
@end
136142

137143
int fibonaccia(int n){

OCRunnerDemo/OCRunnerDemo/ViewController.m

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#import <Masonry/Masonry.h>
1111
#import <MFBlock.h>
1212
#import <WebKit/WebKit.h>
13+
#if __has_include(<Aspects/Aspects.h>)
14+
#import <Aspects/Aspects.h>
15+
#endif
1316

1417
@interface ShareInstance: NSObject
1518
@property (nonatomic,copy)NSDictionary *cache;
@@ -55,7 +58,33 @@ - (void)viewDidLoad {
5558
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
5659
}];
5760
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];
61+
62+
#if __has_include(<Aspects/Aspects.h>)
63+
UIButton *aspectButton = ({
64+
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(50, 300, 150, 50)];
65+
[button setTitle:@"Test Aspect" forState:UIControlStateNormal];
66+
[button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
67+
button.backgroundColor = UIColor.blackColor;
68+
button;
69+
});
70+
[self.view addSubview:aspectButton];
71+
72+
[self aspect_hookSelector:@selector(buttonAction:)
73+
withOptions:AspectPositionBefore
74+
usingBlock:^(id<AspectInfo> aspectInfo, UIButton *sender) {
75+
NSLog(@"buttonAction aspects, sender: %@", sender);
76+
}
77+
error:nil];
78+
#endif
5879
}
80+
81+
#if __has_include(<Aspects/Aspects.h>)
82+
- (void)buttonAction:(UIButton *)sender
83+
{
84+
NSLog(@"buttonAction origin, sender: %@", sender);
85+
}
86+
#endif
87+
5988
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
6089
decisionHandler(WKNavigationActionPolicyAllow);
6190
}

OCRunnerDemo/Podfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ target 'OCRunnerDemo' do
88
pod 'MJRefresh'
99
pod 'MJExtension'
1010
pod 'Masonry'
11+
# pod 'Aspects'
1112

1213
pod 'ORPatchFile', :path => '../oc2mango'
1314
pod 'oc2mangoLib', :path => '../oc2mango'

0 commit comments

Comments
 (0)