// // XSTracker.m // XenonSDK // // Created by SAGESSE on 2019/5/29. // Copyright © 2019 SAGESSE. All rights reserved. // #import "XSTracker.h" #import "XSNetwork.h" #import #import @implementation UIApplication (XSTracker) - (void)sdk_elementEvent:(UIEvent*)sender { [self sdk_elementEvent:sender]; UITouch* touch = sender.allTouches.anyObject; if (touch == nil || ![touch.view isKindOfClass:UIControl.class] || touch.phase != UITouchPhaseEnded) { return; } NSString* str = [[(touch.view.accessibilityLabel ?: touch.view.description) stringByReplacingOccurrencesOfString:@"<" withString:@"<"] stringByReplacingOccurrencesOfString:@">" withString:@">"]; [XSTracker.shared trace:0x020001 parameters:str]; } @end @implementation UIViewController (XSTracker) - (void)sdk_elementAppear:(BOOL)animated { [self sdk_elementAppear:animated]; NSString* name = NSStringFromClass(self.class); if ([name containsString:@"Compatibility"]) { return; } [XSTracker.shared trace:0x040001 parameters:name]; } - (void)sdk_elementDisappear:(BOOL)animated { [self sdk_elementDisappear:animated]; NSString* name = NSStringFromClass(self.class); if ([name containsString:@"Compatibility"]) { return; } [XSTracker.shared trace:0x040002 parameters:name]; } @end @implementation XSTracker XSTracker* sdk_track_shared; + (void)setShared:(XSTracker*)tracker { sdk_track_shared = tracker; static id session = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ session = NSUUID.new.UUIDString; // Injection accessibility checker. // Injection view controller appear tracker. Method m1 = class_getInstanceMethod(UIViewController.class, @selector(viewWillAppear:)); Method m2 = class_getInstanceMethod(UIViewController.class, @selector(sdk_elementAppear:)); method_exchangeImplementations(m1, m2); // Injection view controller disappear tracker. Method m3 = class_getInstanceMethod(UIViewController.class, @selector(viewWillDisappear:)); Method m4 = class_getInstanceMethod(UIViewController.class, @selector(sdk_elementDisappear:)); method_exchangeImplementations(m3, m4); // Injection tap event tracker. Method m5 = class_getInstanceMethod(UIApplication.class, @selector(sendEvent:)); Method m6 = class_getInstanceMethod(UIApplication.class, @selector(sdk_elementEvent:)); method_exchangeImplementations(m5, m6); }); sdk_track_shared.session = session; } + (XSTracker*)shared { return sdk_track_shared; } - (void)trace:(NSInteger)code { [self trace:code parameters:nil]; } - (void)trace:(NSInteger)code parameters:(id)parameters { if ((code & self.mask) == 0) { return; } id extra = [[parameters dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0]; [XSNetwork log:code session:self.session extra:extra ?: @""]; } @end