如何统计一个应用中页面的数据统计,通过swizzleMethod以及友盟统计设计一个分类可简单的实现:
我们通过swizzleMethod修改了UIViewController的@selector(viewWillAppear:)对应的函数指针,使其实现指向了我们自定义的CXX_viewWillAppear的实现.这样,当UIViewController及其子类的对象调用viewWillAppear时,我们可以调用我们自定义的CXX_viewWillAppear,调用到友盟的统计代码,实现代码的注入.
其实也可以理解成交换方法,利用runtime的method_exchangeImplementations交换方法也是可实现的.
如下为分类代码实现:
#import "UIViewController+UMStatistic.h"
#import "MobClick.h"
@implementation UIViewController (UMStatistic)
+(void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
swizzleMethod(class ,@selector(viewWillAppear:),@selector(CXX_viewWillAppear:));
swizzleMethod(class, @selector(viewWillDisappear:), @selector(CXX_viewWillDisappear:));
});
}
void swizzleMethod(Class class,SEL originalSelector,SEL swizzledSelector)
{
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);
}
}
-(void)CXX_viewWillAppear:(BOOL)animated
{
NSString * name = NSStringFromClass([self class]);
if ([name hasPrefix:@"CXX"]) {
[MobClick beginLogPageView:name];
}
}
- (void)CXX_viewWillDisappear:(BOOL)animated
{
NSString * name = NSStringFromClass([self class]);
if ([name hasPrefix:@"CXX"]) {
[MobClick endLogPageView:name];
}
}
@end