XSTracker.m 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. //
  2. // XSTracker.m
  3. // XenonSDK
  4. //
  5. // Created by SAGESSE on 2019/5/29.
  6. // Copyright © 2019 SAGESSE. All rights reserved.
  7. //
  8. #import "XSTracker.h"
  9. #import "XSNetwork.h"
  10. #import <UIKit/UIKit.h>
  11. #import <objc/runtime.h>
  12. @implementation UIApplication (XSTracker)
  13. - (void)sdk_elementEvent:(UIEvent*)sender {
  14. [self sdk_elementEvent:sender];
  15. UITouch* touch = sender.allTouches.anyObject;
  16. if (touch == nil || ![touch.view isKindOfClass:UIControl.class] || touch.phase != UITouchPhaseEnded) {
  17. return;
  18. }
  19. NSString* str = [[(touch.view.accessibilityLabel ?: touch.view.description) stringByReplacingOccurrencesOfString:@"<" withString:@"&lt;"] stringByReplacingOccurrencesOfString:@">" withString:@"&gt;"];
  20. [XSTracker.shared trace:0x020001 parameters:str];
  21. }
  22. @end
  23. @implementation UIViewController (XSTracker)
  24. - (void)sdk_elementAppear:(BOOL)animated {
  25. [self sdk_elementAppear:animated];
  26. NSString* name = NSStringFromClass(self.class);
  27. if ([name containsString:@"Compatibility"]) {
  28. return;
  29. }
  30. [XSTracker.shared trace:0x040001 parameters:name];
  31. }
  32. - (void)sdk_elementDisappear:(BOOL)animated {
  33. [self sdk_elementDisappear:animated];
  34. NSString* name = NSStringFromClass(self.class);
  35. if ([name containsString:@"Compatibility"]) {
  36. return;
  37. }
  38. [XSTracker.shared trace:0x040002 parameters:name];
  39. }
  40. @end
  41. @implementation XSTracker
  42. XSTracker* sdk_track_shared;
  43. + (void)setShared:(XSTracker*)tracker {
  44. sdk_track_shared = tracker;
  45. static id session = nil;
  46. static dispatch_once_t onceToken;
  47. dispatch_once(&onceToken, ^{
  48. session = NSUUID.new.UUIDString;
  49. // Injection accessibility checker.
  50. // Injection view controller appear tracker.
  51. Method m1 = class_getInstanceMethod(UIViewController.class, @selector(viewWillAppear:));
  52. Method m2 = class_getInstanceMethod(UIViewController.class, @selector(sdk_elementAppear:));
  53. method_exchangeImplementations(m1, m2);
  54. // Injection view controller disappear tracker.
  55. Method m3 = class_getInstanceMethod(UIViewController.class, @selector(viewWillDisappear:));
  56. Method m4 = class_getInstanceMethod(UIViewController.class, @selector(sdk_elementDisappear:));
  57. method_exchangeImplementations(m3, m4);
  58. // Injection tap event tracker.
  59. Method m5 = class_getInstanceMethod(UIApplication.class, @selector(sendEvent:));
  60. Method m6 = class_getInstanceMethod(UIApplication.class, @selector(sdk_elementEvent:));
  61. method_exchangeImplementations(m5, m6);
  62. });
  63. sdk_track_shared.session = session;
  64. }
  65. + (XSTracker*)shared {
  66. return sdk_track_shared;
  67. }
  68. - (void)trace:(NSInteger)code {
  69. [self trace:code parameters:nil];
  70. }
  71. - (void)trace:(NSInteger)code parameters:(id)parameters {
  72. if ((code & self.mask) == 0) {
  73. return;
  74. }
  75. id extra = [[parameters dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
  76. [XSNetwork log:code session:self.session extra:extra ?: @""];
  77. }
  78. @end