Skip to content

Commit

Permalink
修改接口,不强制指定 Block 类型。
Browse files Browse the repository at this point in the history
  • Loading branch information
yulingtianxia committed Jul 8, 2019
1 parent 6846bc2 commit 3f33629
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 27 deletions.
2 changes: 1 addition & 1 deletion BlockTracker.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "BlockTracker"
s.version = "1.0.6"
s.version = "1.0.7"
s.summary = "Tracking block args of Objective-C method based on BlockHook"
s.description = <<-DESC
BlockTracker can track block arguments of a method. It's based on BlockHook.
Expand Down
14 changes: 4 additions & 10 deletions BlockTracker/BlockTracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@

NS_ASSUME_NONNULL_BEGIN

/**
追踪回调
@param invocation 被追踪的 block 执行时的 invocation 对象,详见 BHInvocation。
*/
typedef void(^BlockTrackerCallback)(BHInvocation *invocation);

/**
获取元类
Expand Down Expand Up @@ -62,19 +56,19 @@ Class bt_metaClass(Class cls);
追踪方法调用中的 block 参数
@param selector 追踪 block 参数所属的方法
@param callback block 执行前后以及销毁的回调
@param callback block 执行前后以及销毁的回调。第一个参数是 BHInvocation,后面跟着被 Track 的 block 原始的参数列表。
@return 如果追踪成功则返回追踪者对象,否则返回 nil
*/
- (nullable BTTracker *)bt_trackBlockArgOfSelector:(SEL)selector callback:(BlockTrackerCallback)callback;
- (nullable BTTracker *)bt_trackBlockArgOfSelector:(SEL)selector callback:(id)callback;

@end

/**
追踪所有的 `NSMallocBlock`
@param callback block 执行前后以及销毁的回调
@param callback block 执行前后以及销毁的回调。第一个参数是 BHInvocation,后面跟着被 Track 的 block 原始的参数列表。
*/
void setMallocBlockCallback(BlockTrackerCallback callback);
void setMallocBlockCallback(id callback);

NS_ASSUME_NONNULL_END

Expand Down
28 changes: 16 additions & 12 deletions BlockTracker/BlockTracker.m
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ - (void)unlock

@interface BTTracker ()

@property (nonatomic) BlockTrackerCallback callback;
@property (nonatomic) id callback;
@property (nonatomic) NSArray<NSNumber *> *blockArgIndex;
@property (nonatomic) SEL aliasSelector;
@property (nonatomic, readwrite, getter=isActive) BOOL active;
@property (nonatomic) NSHashTable *blockHookTokens;
@property (nonatomic) NSHashTable *blocksAlreadyHooked;
- (instancetype)initWithTarget:(id)target selector:(SEL)selector;

/**
Expand All @@ -141,7 +141,7 @@ - (instancetype)initWithTarget:(id)target selector:(SEL)selector
if (self) {
_target = target;
_selector = selector;
_blockHookTokens = [NSHashTable weakObjectsHashTable];
_blocksAlreadyHooked = [NSHashTable weakObjectsHashTable];
}
return self;
}
Expand Down Expand Up @@ -423,15 +423,19 @@ static void bt_handleInvocation(NSInvocation *invocation, BTTracker *tracker)
if (index.integerValue < invocation.methodSignature.numberOfArguments) {
__unsafe_unretained id block;
[invocation getArgument:&block atIndex:index.integerValue];
if ([tracker.blockHookTokens containsObject:block]) {
if ([tracker.blocksAlreadyHooked containsObject:block]) {
continue;
}
// It's a weak reference.
[tracker.blockHookTokens addObject:block];

[block block_hookWithMode:BlockHookModeBefore|BlockHookModeAfter|BlockHookModeDead usingBlock:tracker.callback];

NSLog(@"Hook Block Arg mangleName:%@, in selector:%@", [block block_currentHookToken].mangleName, NSStringFromSelector(tracker.selector));
BHToken *token = [block block_hookWithMode:BlockHookModeBefore|BlockHookModeAfter|BlockHookModeDead usingBlock:tracker.callback];
if (token) {
// It's a weak reference.
[tracker.blocksAlreadyHooked addObject:block];
NSLog(@"Hook Block Arg mangleName:%@, in selector:%@", [block block_currentHookToken].mangleName, NSStringFromSelector(tracker.selector));
}
else {
NSLog(@"Hook Block Arg Failed! Method:%@, block arg:%@", NSStringFromSelector(tracker.selector), block);
}
}
}
invocation.selector = tracker.aliasSelector;
Expand Down Expand Up @@ -697,7 +701,7 @@ @implementation NSObject (BlockTracker)
return [result copy];
}

- (nullable BTTracker *)bt_trackBlockArgOfSelector:(SEL)selector callback:(BlockTrackerCallback)callback
- (nullable BTTracker *)bt_trackBlockArgOfSelector:(SEL)selector callback:(id)callback
{
Method originMethod = class_getInstanceMethod([self class], selector);
if (!originMethod) {
Expand Down Expand Up @@ -737,7 +741,7 @@ - (nullable BTTracker *)bt_trackBlockArgOfSelector:(SEL)selector callback:(Block
@end

static void *(*bt_orig_Block_copy)(const void *aBlock);
static BlockTrackerCallback bt_blockTrackerCallback;
static id bt_blockTrackerCallback;

void *bt_replaced_Block_copy(const void *aBlock)
{
Expand All @@ -749,7 +753,7 @@ - (nullable BTTracker *)bt_trackBlockArgOfSelector:(SEL)selector callback:(Block
return result;
}

void setMallocBlockCallback(BlockTrackerCallback callback) {
void setMallocBlockCallback(id callback) {
bt_blockTrackerCallback = callback;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Expand Down
11 changes: 7 additions & 4 deletions BlockTrackerSampleTests/BlockTrackerSampleTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ - (void)tearDown {

- (void)testTrackMethod {
XCTestExpectation *expectation = [[XCTestExpectation alloc] initWithDescription:@"Wait for block invoke."];
__unused BTTracker *tracker = [self bt_trackBlockArgOfSelector:@selector(performBlock:) callback:^(BHInvocation * _Nonnull invocation) {
__unused BTTracker *tracker = [self bt_trackBlockArgOfSelector:@selector(performBlock:) callback:^(BHInvocation * _Nonnull invocation, int a) {
switch (invocation.mode) {
case BlockHookModeBefore:
NSAssert(a == 1, @"参数传递错误");
NSLog(@"Before block:%@, mangleName:%@", invocation.token.block, invocation.token.mangleName);
break;
case BlockHookModeAfter:
Expand All @@ -49,7 +50,7 @@ - (void)testTrackMethod {

// invoke blocks
NSString *word = @"I'm a block";
[self performBlock:^{
[self performBlock:^(int a){
NSLog(@"%@", word);
[expectation fulfill];
}];
Expand Down Expand Up @@ -83,8 +84,10 @@ - (void)testTrackAllMallocBlock {
});
}

- (void)performBlock:(void(^)(void))block {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), block);
- (void)performBlock:(void(^)(int))block {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
block(1);
});
}

@end

0 comments on commit 3f33629

Please sign in to comment.