Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add message prefix to avoid crash #142

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Aspects.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@

#import <Foundation/Foundation.h>

@interface AspectManager : NSObject

@property (nonatomic, copy) NSArray <NSString *> *messagePrefixArray;

+ (instancetype)shareManager;

@end

typedef NS_OPTIONS(NSUInteger, AspectOptions) {
AspectPositionAfter = 0, /// Called after the original implementation (default)
AspectPositionInstead = 1, /// Will replace the original implementation.
Expand Down
29 changes: 29 additions & 0 deletions Aspects.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@
#import <objc/runtime.h>
#import <objc/message.h>

@implementation AspectManager

+ (instancetype)shareManager {
static AspectManager *shareManager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shareManager = [[AspectManager alloc] init];
});
return shareManager;
}

@end

#define AspectLog(...)
//#define AspectLog(...) do { NSLog(__VA_ARGS__); }while(0)
#define AspectLogError(...) do { NSLog(__VA_ARGS__); }while(0)
Expand Down Expand Up @@ -474,6 +487,22 @@ static void aspect_undoSwizzleClassInPlace(Class klass) {
static void __ASPECTS_ARE_BEING_CALLED__(__unsafe_unretained NSObject *self, SEL selector, NSInvocation *invocation) {
NSCParameterAssert(self);
NSCParameterAssert(invocation);
/*
The aspects framework hook firstly and later other aop framework hook a same method, which will cause crash.
*/
NSString *selectorStr = NSStringFromSelector(invocation.selector);
if ([AspectManager shareManager].messagePrefixArray.count > 0) {
[[AspectManager shareManager].messagePrefixArray enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([selectorStr hasPrefix:obj]) {
NSString *cstr =
[selectorStr stringByReplacingCharactersInRange:NSMakeRange(0, obj.length)
withString:@""];
invocation.selector = NSSelectorFromString(cstr);
*stop = YES;
}
}];
}

SEL originalSelector = invocation.selector;
SEL aliasSelector = aspect_aliasForSelector(invocation.selector);
invocation.selector = aliasSelector;
Expand Down
14 changes: 14 additions & 0 deletions AspectsDemo/AspectsDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
78573F2519155A74000D3B00 /* Aspects.m in Sources */ = {isa = PBXBuildFile; fileRef = 78573F2319155A74000D3B00 /* Aspects.m */; };
78D7D77119177C8E002EB314 /* AspectsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 78D7D76F19177C8E002EB314 /* AspectsViewController.m */; };
78D7D77219177C8E002EB314 /* AspectsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 78D7D77019177C8E002EB314 /* AspectsViewController.xib */; };
BA8B9D77205F635C00D6AA5B /* AspectsSwizz.m in Sources */ = {isa = PBXBuildFile; fileRef = BA8B9D76205F635C00D6AA5B /* AspectsSwizz.m */; };
BA8B9D79205F645D00D6AA5B /* AspectsHookTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BA8B9D78205F645D00D6AA5B /* AspectsHookTests.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -56,6 +58,9 @@
78D7D76E19177C8E002EB314 /* AspectsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AspectsViewController.h; sourceTree = "<group>"; };
78D7D76F19177C8E002EB314 /* AspectsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AspectsViewController.m; sourceTree = "<group>"; };
78D7D77019177C8E002EB314 /* AspectsViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AspectsViewController.xib; sourceTree = "<group>"; };
BA8B9D75205F635C00D6AA5B /* AspectsSwizz.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AspectsSwizz.h; sourceTree = "<group>"; };
BA8B9D76205F635C00D6AA5B /* AspectsSwizz.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AspectsSwizz.m; sourceTree = "<group>"; };
BA8B9D78205F645D00D6AA5B /* AspectsHookTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AspectsHookTests.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -124,6 +129,8 @@
78D7D76E19177C8E002EB314 /* AspectsViewController.h */,
78D7D76F19177C8E002EB314 /* AspectsViewController.m */,
78D7D77019177C8E002EB314 /* AspectsViewController.xib */,
BA8B9D75205F635C00D6AA5B /* AspectsSwizz.h */,
BA8B9D76205F635C00D6AA5B /* AspectsSwizz.m */,
);
path = AspectsDemo;
sourceTree = "<group>";
Expand All @@ -143,6 +150,7 @@
isa = PBXGroup;
children = (
78573F1919155A2E000D3B00 /* AspectsDemoTests.m */,
BA8B9D78205F645D00D6AA5B /* AspectsHookTests.m */,
78573F1419155A2E000D3B00 /* Supporting Files */,
);
path = AspectsDemoTests;
Expand Down Expand Up @@ -256,6 +264,7 @@
files = (
78D7D77119177C8E002EB314 /* AspectsViewController.m in Sources */,
78573F0519155A2E000D3B00 /* AspectsAppDelegate.m in Sources */,
BA8B9D77205F635C00D6AA5B /* AspectsSwizz.m in Sources */,
78573F2519155A74000D3B00 /* Aspects.m in Sources */,
78573F0119155A2E000D3B00 /* main.m in Sources */,
);
Expand All @@ -265,6 +274,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BA8B9D79205F645D00D6AA5B /* AspectsHookTests.m in Sources */,
78573F1A19155A2E000D3B00 /* AspectsDemoTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -413,6 +423,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AspectsDemo/AspectsDemo-Prefix.pch";
INFOPLIST_FILE = "AspectsDemo/AspectsDemo-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
Expand All @@ -426,6 +437,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AspectsDemo/AspectsDemo-Prefix.pch";
INFOPLIST_FILE = "AspectsDemo/AspectsDemo-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
Expand All @@ -447,6 +459,7 @@
"$(inherited)",
);
INFOPLIST_FILE = "AspectsDemoTests/AspectsDemoTests-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
Expand All @@ -465,6 +478,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AspectsDemo/AspectsDemo-Prefix.pch";
INFOPLIST_FILE = "AspectsDemoTests/AspectsDemoTests-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
Expand Down
22 changes: 22 additions & 0 deletions AspectsDemo/AspectsDemo/AspectsSwizz.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// AspectsSwizz.h
// AspectsDemo
//
// Created by Justin.wang on 2018/3/19.
// Copyright © 2018年 PSPDFKit GmbH. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface AspectsSwizz : NSObject

+ (void)swizzingInstanceMethodByClass:(Class)cls
originSelector:(SEL)originSelector
swizzingSelector:(SEL)swizzingSelector;

+ (void)swizzingClassMethodByClass:(Class)cls
originSelector:(SEL)originSelector
swizzingSelector:(SEL)swizzingSelector;

@end
71 changes: 71 additions & 0 deletions AspectsDemo/AspectsDemo/AspectsSwizz.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// AspectsSwizz.m
// AspectsDemo
//
// Created by Justin.wang on 2018/3/19.
// Copyright © 2018年 PSPDFKit GmbH. All rights reserved.
//

#import "AspectsSwizz.h"

@implementation AspectsSwizz

+ (void)swizzingInstanceMethodByClass:(Class)cls
originSelector:(SEL)originSelector
swizzingSelector:(SEL)swizzingSelector {
NSParameterAssert(cls);
NSParameterAssert(originSelector);
NSParameterAssert(swizzingSelector);

Method originalMethod = class_getInstanceMethod(cls, originSelector);
Method swizzledMethod = class_getInstanceMethod(cls, swizzingSelector);

if (originalMethod && swizzledMethod) {
BOOL didAddMethod =
class_addMethod(cls,
originSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));

if (didAddMethod) {
class_replaceMethod(cls,
swizzingSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
}

+ (void)swizzingClassMethodByClass:(Class)cls
originSelector:(SEL)originSelector
swizzingSelector:(SEL)swizzingSelector {
NSParameterAssert(cls);
NSParameterAssert(originSelector);
NSParameterAssert(swizzingSelector);

Method originalMethod = class_getClassMethod(cls, originSelector);
Method swizzledMethod = class_getClassMethod(cls, swizzingSelector);

cls = object_getClass((id)cls);

if (originalMethod && swizzledMethod) {
BOOL didAddMethod =
class_addMethod(cls,
originSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));

if (didAddMethod) {
class_replaceMethod(cls,
swizzingSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
}

@end
60 changes: 60 additions & 0 deletions AspectsDemo/AspectsDemoTests/AspectsHookTests.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// AspectsHookTests.m
// AspectsDemoTests
//
// Created by Justin.wang on 2018/3/19.
// Copyright © 2018年 PSPDFKit GmbH. All rights reserved.
//

#import <XCTest/XCTest.h>
#import "Aspects.h"
#import "AspectsSwizz.h"

@interface UIViewController (Hook)

@end

@implementation UIViewController (Hook)

- (void)hook_viewDidAppear:(BOOL)animated {
NSLog(@"Hook viewDidAppear");
[self hook_viewDidAppear:animated];
}

@end


@interface AspectsHookTests : XCTestCase

@end

@implementation AspectsHookTests

- (void)testOtherAopFrameworkHookLater {
[[UIViewController class] aspect_hookSelector:@selector(viewDidAppear:)
withOptions:AspectPositionBefore
usingBlock:^(id invoke) {
NSLog(@"Aspects viewDidAppear");
} error:NULL];

[AspectsSwizz swizzingInstanceMethodByClass:[UIViewController class]
originSelector:@selector(viewDidAppear:)
swizzingSelector:@selector(hook_viewDidAppear:)];
UIViewController *vc = [[UIViewController alloc] init];
@try {
[vc viewDidAppear:YES];
XCTAssertTrue(NO, @"viewDidAppear should throw a exception");
} @catch (NSException *e) {
XCTAssertTrue(YES, @"should catch a exception");
}

[AspectManager shareManager].messagePrefixArray= @[@"hook_"];
@try {
[vc viewDidAppear:YES];
} @catch (NSException *e) {
XCTAssertTrue(NO, @"should not throw a exception");
}
}


@end