Skip to content

Commit

Permalink
release 0.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
李杰 committed Oct 19, 2018
1 parent 32eb200 commit 658b09c
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 35 deletions.
2 changes: 1 addition & 1 deletion JJException.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Pod::Spec.new do |s|
#

s.name = "JJException"
s.version = "0.1.0"
s.version = "0.1.1"
s.summary = "Handle the objective-c crash exception."

# This description is used to generate tags and improve search results.
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "JJException/Source/MRC/NSObject+KVOCrash.m"
timestampString = "561277038.212747"
filePath = "JJException/Source/MRC/NSObject+UnrecognizedSelectorHook.m"
timestampString = "561397405.780197"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "138"
endingLineNumber = "138"
landmarkName = "-clearKVOData"
landmarkType = "7">
startingLineNumber = "10"
endingLineNumber = "10"
landmarkName = "unknown"
landmarkType = "0">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
Expand All @@ -25,35 +25,30 @@
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "JJException/Source/MRC/NSObject+KVOCrash.m"
timestampString = "561277038.213109"
filePath = "JJException/Source/ARC/NSNotificationCenter+ClearNotification.m"
timestampString = "561635354.75411"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "187"
endingLineNumber = "187"
landmarkName = "-hookAddObserver:forKeyPath:options:context:"
startingLineNumber = "29"
endingLineNumber = "29"
landmarkName = "-processAddObserver:selector:name:object:swizzleInfo:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.SymbolicBreakpoint">
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "[NSObject addObserver:forKeyPath:options:context:]"
moduleName = "">
<Locations>
<Location
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "-[NSObject(NSKeyValueObserverRegistration) addObserver:forKeyPath:options:context:]"
moduleName = "Foundation"
usesParentBreakpointCondition = "Yes"
offsetFromSymbolStart = "0">
</Location>
</Locations>
filePath = "JJException/Source/Swizzle/NSObject+SwizzleHook.m"
timestampString = "561635354.754173"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "109"
endingLineNumber = "109"
landmarkName = "__JJ_SWIZZLE_BLOCK"
landmarkType = "9">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
Expand Down
12 changes: 9 additions & 3 deletions JJException/Source/ARC/NSNotificationCenter+ClearNotification.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,23 @@
@implementation NSNotificationCenter (ClearNotification)

+ (void)jj_swizzleNSNotificationCenter{
swizzleInstanceMethod([NSNotificationCenter class], @selector(addObserver:selector:name:object:), @selector(hookAddObserver:selector:name:object:));
[self jj_swizzleInstanceMethod:@selector(addObserver:selector:name:object:) withSwizzledBlock:^id(JJSwizzleObject *swizzleInfo) {
return ^(__unsafe_unretained id self,id observer,SEL aSelector,NSString* aName,id anObject){
[self processAddObserver:observer selector:aSelector name:aName object:anObject swizzleInfo:swizzleInfo];
};
}];
}

- (void)hookAddObserver:(id)observer selector:(SEL)aSelector name:(NSNotificationName)aName object:(id)anObject{
- (void)processAddObserver:(id)observer selector:(SEL)aSelector name:(NSNotificationName)aName object:(id)anObject swizzleInfo:(JJSwizzleObject*)swizzleInfo{

if (observer) {
__unsafe_unretained typeof(observer) unsafeObject = observer;
[observer jj_deallocBlock:^{
[[NSNotificationCenter defaultCenter] removeObserver:unsafeObject];
}];
[self hookAddObserver:observer selector:aSelector name:aName object:anObject];
void(*originIMP)(__unsafe_unretained id,SEL,id,SEL,NSString*,id);
originIMP = (__typeof(originIMP))[swizzleInfo getOriginalImplementation];
originIMP(self,swizzleInfo.selector,observer,aSelector,aName,anObject);
}
}

Expand Down
14 changes: 14 additions & 0 deletions JJException/Source/Swizzle/NSObject+SwizzleHook.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@

#import <Foundation/Foundation.h>

typedef void (*JJSwizzleOriginalIMP)(void /* id, SEL, ... */ );

@interface JJSwizzleObject : NSObject

- (JJSwizzleOriginalIMP)getOriginalImplementation;

@property (nonatomic,readonly,assign) SEL selector;

@end

typedef id (^JJSwizzledIMPBlock)(JJSwizzleObject* swizzleInfo);

void swizzleClassMethod(Class cls, SEL originSelector, SEL swizzleSelector);

void swizzleInstanceMethod(Class cls, SEL originSelector, SEL swizzleSelector);
Expand All @@ -18,4 +30,6 @@ void swizzleInstanceMethod(Class cls, SEL originSelector, SEL swizzleSelector);

- (void)jj_swizzleInstanceMethod:(SEL)originSelector withSwizzleMethod:(SEL)swizzleSelector;

- (void)jj_swizzleInstanceMethod:(SEL)originSelector withSwizzledBlock:(JJSwizzledIMPBlock)swizzledBlock;

@end
56 changes: 52 additions & 4 deletions JJException/Source/Swizzle/NSObject+SwizzleHook.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,25 @@

#import "NSObject+SwizzleHook.h"
#import <objc/runtime.h>
#import <libkern/OSAtomic.h>

void swizzleClassMethod(Class cls, SEL originSelector, SEL swizzleSelector)
{
typedef IMP (^JJSWizzleImpProvider)(void);

@interface JJSwizzleObject()
@property (nonatomic,readwrite,copy) JJSWizzleImpProvider impProviderBlock;
@property (nonatomic,readwrite,assign) SEL selector;
@end

@implementation JJSwizzleObject

- (JJSwizzleOriginalIMP)getOriginalImplementation{
NSAssert(_impProviderBlock,nil);
return (JJSwizzleOriginalIMP)_impProviderBlock();
}

@end

void swizzleClassMethod(Class cls, SEL originSelector, SEL swizzleSelector){
if (!cls) {
return;
}
Expand Down Expand Up @@ -40,8 +56,7 @@ void swizzleClassMethod(Class cls, SEL originSelector, SEL swizzleSelector)
}
}

void swizzleInstanceMethod(Class cls, SEL originSelector, SEL swizzleSelector)
{
void swizzleInstanceMethod(Class cls, SEL originSelector, SEL swizzleSelector){
if (!cls) {
return;
}
Expand Down Expand Up @@ -75,6 +90,35 @@ void swizzleInstanceMethod(Class cls, SEL originSelector, SEL swizzleSelector)

@implementation NSObject (SwizzleHook)

void __JJ_SWIZZLE_BLOCK(Class classToSwizzle,SEL selector,JJSwizzledIMPBlock impBlock){
Method method = class_getInstanceMethod(classToSwizzle, selector);

__block IMP originalIMP = NULL;

JJSWizzleImpProvider originalImpProvider = ^IMP{

IMP imp = originalIMP;

if (NULL == imp){
Class superclass = class_getSuperclass(classToSwizzle);
imp = method_getImplementation(class_getInstanceMethod(superclass,selector));
}
return imp;
};

JJSwizzleObject* swizzleInfo = [JJSwizzleObject new];
swizzleInfo.selector = selector;
swizzleInfo.impProviderBlock = originalImpProvider;

id newIMPBlock = impBlock(swizzleInfo);

const char* methodType = method_getTypeEncoding(method);

IMP newIMP = imp_implementationWithBlock(newIMPBlock);

originalIMP = class_replaceMethod(classToSwizzle, selector, newIMP, methodType);
}

+ (void)jj_swizzleClassMethod:(SEL)originSelector withSwizzleMethod:(SEL)swizzleSelector{
swizzleClassMethod(self.class, originSelector, swizzleSelector);
}
Expand All @@ -83,4 +127,8 @@ - (void)jj_swizzleInstanceMethod:(SEL)originSelector withSwizzleMethod:(SEL)swiz
swizzleInstanceMethod(self.class, originSelector, swizzleSelector);
}

- (void)jj_swizzleInstanceMethod:(SEL)originSelector withSwizzledBlock:(JJSwizzledIMPBlock)swizzledBlock{
__JJ_SWIZZLE_BLOCK(self.class, originSelector, swizzledBlock);
}

@end
4 changes: 3 additions & 1 deletion JJExceptionPrinciple.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,9 @@ Method swizzling整个过程需要线程安全,如果你只是在`+(void)load`

A类有一个方法a1,Swizzled的方法是a2,在执行原始方法时,取_cmd参数时是`a2`,如果a1方法体里有依赖_cmd时,就会出现问题。

所以`RSSwizzle``Aspects`都是用block来规避这个问题的,__所以在JJException的0.1.1版本中将用RSSwizzle的方式来实现Hook__
`RSSwizzle`是用block和IMP来规避这个问题的,`RSSwizzle`是真正避开这个问题的,因为对外接口就是IMP,所以他用宏对外,使用的比较生涩.

`Aspects`其实没有安全避开这个问题,不过它主要保证`forwardInvocation:`没有依赖_cmd,就没有这个问题.

* Swizzle执行顺序

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ typedef NS_OPTIONS(NSInteger,JJExceptionGuardCategory){
};
```
* 设置异常类型并开启
* 设置异常类型并开启,__建议放在`didFinishLaunchingWithOptions`第一行,以免在多线程出现异常的情况__
```objc
[JJException configExceptionCategory:JJExceptionGuardAll];
[JJException startGuardException];
Expand Down

0 comments on commit 658b09c

Please sign in to comment.