test--runtime

2018-07-25  本文已影响5人  乂滥好人

参考:
https://www.jianshu.com/p/6ebda3cd8052
https://www.cnblogs.com/nbhhcty66/p/7070478.html http://www.cocoachina.com/ios/20170228/18798.html

1、快速定位当前显示控制器(注:无需import文件,方便接手老项目时快速找到控制器)

//  UIViewController+Swizzling.h

#import <UIKit/UIKit.h>

@interface UIViewController (Swizzling)

@end
//
//  UIViewController+Swizzling.m

#import "UIViewController+Swizzling.h"
#import <objc/runtime.h>

@implementation UIViewController (Swizzling)

+ (void)load
{
#ifdef DEBUG
    // 自定义方法交换系统方法,打印控制器名称,快速定位当前控制器
    Method m1 = class_getInstanceMethod(self, @selector(viewWillAppear:));
    Method m2 = class_getInstanceMethod(self, @selector(logViewWillAppear:));
    method_exchangeImplementations(m1, m2);
#endif
}

- (void)logViewWillAppear:(BOOL)animated
{
    NSString *className = NSStringFromClass([self class]);
    // 过滤系统控制器
    if (![className hasPrefix:@"UI"]) {
        NSLog(@"【%@】即将显示",className);
    }
    // 不干扰原代码流程,代码结束后要让本该执行的代码继续执行
    [self logViewWillAppear:animated];
}

@end

log(注:即使当前控制器已实现此方法,也会先调用上面自定义分类的自定义方法)

2018-07-25 15:58:21.435558+0800 RuntimeDome[5626:242889] 【ViewController】即将显示
2018-07-25 15:58:22.669172+0800 RuntimeDome[5626:242889] 【TestViewController】即将显示
2018-07-25 15:58:22.669328+0800 RuntimeDome[5626:242889] TestViewController中实现了viewWillAppear方法

2、控制器打点,统计控制器展示次数

2.1、工具类

//  StatisticalTool.h
@interface StatisticalTool : NSObject
+ (void)swizzlingInClass:(Class)cls originalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector;
@end


// StatisticalTool.m
@implementation StatisticalTool

+ (void)swizzlingInClass:(Class)cls originalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector
{
    Class class = cls;
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

    BOOL didAddMethod =
    class_addMethod(class,
                    originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));

    if (didAddMethod) {
        class_replaceMethod(class,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}
@end

2.2、使用

#import "UIViewController+Swizzling.h"
#import "StatisticalTool.h"

@implementation UIViewController (Swizzling)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(swiz_viewWillAppear:);
        [WHookUtility swizzlingInClass:[self class] originalSelector:originalSelector swizzledSelector:swizzledSelector];
    });
}

/** 自定义方法,在此进行所有控制器数据统计 */
- (void)swiz_viewWillAppear:(BOOL)animated
{
    NSLog(@"在此进行所有控制器数据统计,完成控制器打点");
    // 不干扰原代码流程,代码结束后要让本该执行的代码继续执行
    [self swiz_viewWillAppear:animated];
}
@end

log: 
2018-07-25 16:53:21.611699+0800 RuntimeDome[6233:280367] 在此进行所有控制器数据统计,完成控制器打点

3、Button间隔点击

3.1、创建UIControl分类

#import <UIKit/UIKit.h>

@interface UIControl (userClick)
/** 时间间隔 */
@property (nonatomic, assign) NSTimeInterval durationTime;

@end
#import "UIControl+userClick.h"
#import "WHookUtility.h"
#import <objc/runtime.h>

@implementation UIControl (userClick)

static const char *ButtonDurationTime = "ButtonDurationTime";

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL originalSelector = @selector(sendAction:to:forEvent:);
        SEL swizzledSelector = @selector(swiz_sendAction:to:forEvent:);
        [WHookUtility swizzlingInClass:[self class] originalSelector:originalSelector swizzledSelector:swizzledSelector];
    });
}

- (void)swiz_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
    self.userInteractionEnabled = NO;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.durationTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.userInteractionEnabled = YES;
    });

    [self swiz_sendAction:action to:target forEvent:event];
}

#pragma mark - runtime关联属性对象
- (NSTimeInterval)durationTime
{
    NSNumber *number = objc_getAssociatedObject(self, &ButtonDurationTime);
    return number.doubleValue;
}

- (void)setDurationTime:(NSTimeInterval)durationTime
{
    NSNumber *number = [NSNumber numberWithDouble:durationTime];
    objc_setAssociatedObject(self, &ButtonDurationTime, number, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end

3.2、使用:

①、头文件
#import "UIControl+userClick.h"

②、设置间隔时长
button.durationTime = 3.f;
上一篇 下一篇

猜你喜欢

热点阅读