- 重載類的“+(void)load”方法释簿,在程序加載到內(nèi)存時利用Runtime的
method_exchangeImplementations
等接口將方法的實現(xiàn)互相交換匹涮。當(dāng)方法被調(diào)用時就會被勾住(Hook)孵户,執(zhí)行我們的方法宵距。
@interface HookUtility : NSObject
+ (void)swizzlingInClass:(Class)cls originalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector;
@end
@implementation HookUtility
+ (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
- 頁面進(jìn)入的埋點統(tǒng)計,交換ViewController的DidAppear方法的實現(xiàn)以ViewController的類名為識別符進(jìn)行埋點統(tǒng)計略荡。
@implementation UIViewController (userStastistics)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL originalSelector = @selector(viewWillAppear:);
SEL swizzledSelector = @selector(swiz_viewWillAppear:);
[HookUtility swizzlingInClass:[self class] originalSelector:originalSelector swizzledSelector:swizzledSelector];
});
}
- (void)swiz_viewWillAppear:(BOOL)animated {
// 埋點上報
NSString *targetName = NSStringFromClass([self class]);
NSLog(@"上報到數(shù)據(jù)統(tǒng)計中心的targetName=%@", targetName);
// 執(zhí)行被交換的實現(xiàn)
[self swiz_viewWillAppear:animated];
}
@end
- 控件交互事件(點擊庵佣、拖動、雙擊...)的埋點統(tǒng)計汛兜,交換
sendAction:to:forEvent:
方法實現(xiàn)巴粪,以按鈕的“類名+target名+action名”作為識別符上報數(shù)據(jù)統(tǒng)計中心
@implementation UIControl (userStastistics)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL originalSelector = @selector(sendAction:to:forEvent:);
SEL swizzledSelector = @selector(swiz_sendAction:to:forEvent:);
[HookUtility swizzlingInClass:[self class] originalSelector:originalSelector swizzledSelector:swizzledSelector];
});
}
- (void)swiz_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
//插入埋點代碼
[self performUserStastisticsAction:action to:target forEvent:event];
// 執(zhí)行被交換的實現(xiàn)
[self swiz_sendAction:action to:target forEvent:event];
}
- (void)performUserStastisticsAction:(SEL)action to:(id)target forEvent:(UIEvent *)event; {
NSString *className = NSStringFromClass([self class]);
NSString *targetName = NSStringFromClass([target class]);
NSString *actionString = NSStringFromSelector(action);
NSLog(@"上報到數(shù)據(jù)統(tǒng)計中心=%@_%@_%@", className, targetName, actionString);
}
@end
- 擴展-頁面停留時長統(tǒng)計:可通過以上ViewController的擴展類去擴展屬性,在DidAppear方法里給該屬性賦值粥谬,在DidDisappear方法里計算時間差并且交換方法實現(xiàn)達(dá)到頁面停留時長埋點需求
- 擴展-批量上報/實時上報:通過本地plist配置文件去自定義一些特殊行為肛根。