From a7351377c1bfe28bdd464a232f7f3cca2fd880df Mon Sep 17 00:00:00 2001 From: "Alyssa.Yu" Date: Wed, 6 Sep 2023 16:32:58 -0700 Subject: [PATCH] feat: feat: swizzled on app will appear --- Sources/Amplitude/Amplitude.m | 1 + .../Amplitude/UIViewController+AMPScreen.h | 1 + .../Amplitude/UIViewController+AMPScreen.m | 97 ++++++++++++++++--- 3 files changed, 88 insertions(+), 11 deletions(-) diff --git a/Sources/Amplitude/Amplitude.m b/Sources/Amplitude/Amplitude.m index be35ee25..3c14d71d 100644 --- a/Sources/Amplitude/Amplitude.m +++ b/Sources/Amplitude/Amplitude.m @@ -543,6 +543,7 @@ - (void)initializeApiKey:(NSString *)apiKey // Unlike other default events options that can be evaluated later, screenViews has to be evaluated during the actual initialization if (self.defaultTracking.screenViews) { [UIViewController amp_swizzleViewDidAppear]; + [UIViewController amp_swizzleViewWillAppear]; } #endif }]; diff --git a/Sources/Amplitude/UIViewController+AMPScreen.h b/Sources/Amplitude/UIViewController+AMPScreen.h index f8443378..406ebea5 100644 --- a/Sources/Amplitude/UIViewController+AMPScreen.h +++ b/Sources/Amplitude/UIViewController+AMPScreen.h @@ -27,6 +27,7 @@ @interface UIViewController (AMPScreen) + (void)amp_swizzleViewDidAppear; ++ (void)amp_swizzleViewWillAppear; + (UIViewController *)amp_rootViewControllerFromView:(UIView *)view; + (UIViewController *)amp_topViewController:(UIViewController *)rootViewController; diff --git a/Sources/Amplitude/UIViewController+AMPScreen.m b/Sources/Amplitude/UIViewController+AMPScreen.m index 1568a860..eb5fdf0d 100644 --- a/Sources/Amplitude/UIViewController+AMPScreen.m +++ b/Sources/Amplitude/UIViewController+AMPScreen.m @@ -39,9 +39,6 @@ #import "AMPConstants.h" #import -static NSNotificationName const __UIWindowSceneDidChangeScreenNotification = @"__UIWindowSceneDidChangeScreenNotification"; - - #if !TARGET_OS_OSX && !TARGET_OS_WATCH @@ -75,6 +72,35 @@ + (void)amp_swizzleViewDidAppear { }); } ++ (void)amp_swizzleViewWillAppear { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class class = [self class]; + + SEL originalSelector = @selector(viewWillAppear:); + SEL swizzledSelector = @selector(amp_viewWillAppear:); + + 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); + } + }); +} + + + (UIViewController *)amp_rootViewControllerFromView:(UIView *)view { UIViewController *root = view.window.rootViewController; @@ -120,7 +146,8 @@ + (UIViewController *)amp_nextRootViewController:(UIViewController *)rootViewCon return nil; } -- (void)amp_viewDidAppear:(BOOL)animated { + +- (void)amp_viewWillAppear:(BOOL)animated { AMPLITUDE_LOG(@"self is %@", self); UIViewController *top = [[self class] amp_rootViewControllerFromView:self.view]; if (!top) { @@ -137,13 +164,57 @@ - (void)amp_viewDidAppear:(BOOL)animated { name = @"Unknown"; } } + + NSLog(@"**********view will appear**********"); + //NSLog(@"Screen changed!"); + + printViewHierarchy(self.view, 0); + +/* + UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0f); + [self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:NO]; + UIImage *snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); +*/ + + [[Amplitude instance] logEvent:kAMPScreenViewed withEventProperties:@{ + kAMPEventPropScreenName: name ?: @"", + }]; + + // call original method, this is not recurrsive method call + [self amp_viewWillAppear:animated]; +} + +- (void)amp_viewDidAppear:(BOOL)animated { + AMPLITUDE_LOG(@"self is %@", self); + UIViewController *top = [[self class] amp_rootViewControllerFromView:self.view]; + if (!top) { + AMPLITUDE_LOG(@"Failed to infer screen"); + return; + } - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(screenChanged:) - name:__UIWindowSceneDidChangeScreenNotification - object:nil]; + NSString *name = [top title]; + if (!name || name.length == 0) { + // if no class title found, try view controller's description + name = [[[top class] description] stringByReplacingOccurrencesOfString:@"ViewController" withString:@""]; + if (name.length == 0) { + AMPLITUDE_LOG(@"Failed to infer screen name"); + name = @"Unknown"; + } + } + + NSLog(@"**********View did appear**********"); + //NSLog(@"Screen changed!"); + printViewHierarchy(self.view, 0); +/* + UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0f); + [self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:NO]; + UIImage *snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); +*/ + [[Amplitude instance] logEvent:kAMPScreenViewed withEventProperties:@{ kAMPEventPropScreenName: name ?: @"", }]; @@ -152,12 +223,16 @@ - (void)amp_viewDidAppear:(BOOL)animated { [self amp_viewDidAppear:animated]; } -- (void)screenChanged:(NSNotification *)notification { +/* + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(screenChanged:) name:@"screenChanged" object:nil]; + //UIAccessibilityScreenChangedNotification + + - (void)screenChanged:(NSNotification *)notification { // Handle the screen change here NSLog(@"**********Before print view hierarchy**********"); NSLog(@"Screen changed!"); printViewHierarchy(self.view, 0); -} +}*/ void printViewHierarchy(UIView *view, int indent) { NSMutableString *indentation = [NSMutableString string]; @@ -170,6 +245,6 @@ void printViewHierarchy(UIView *view, int indent) { printViewHierarchy(subview, indent + 4); } } - +// city of staff person. @end #endif