Skip to content

Commit 4bf0706

Browse files
committed
view 采集逻辑调整,防止侧滑重复采集view,子视图采集逻辑调整
1 parent fad3d59 commit 4bf0706

File tree

6 files changed

+157
-43
lines changed

6 files changed

+157
-43
lines changed

FTMobileSDK.xcodeproj/project.pbxproj

+16
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,12 @@
437437
17AC174E2B98635C003E18A6 /* NSDate+FTUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 17AC174A2B98635C003E18A6 /* NSDate+FTUtil.m */; };
438438
17AC174F2B98635C003E18A6 /* NSDate+FTUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 17AC174A2B98635C003E18A6 /* NSDate+FTUtil.m */; };
439439
17AC17502B98635C003E18A6 /* NSDate+FTUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 17AC174A2B98635C003E18A6 /* NSDate+FTUtil.m */; };
440+
17BCF37E2D66EB2A009A63FD /* FTWeakPropertyContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 17BCF37D2D66EB2A009A63FD /* FTWeakPropertyContainer.m */; };
441+
17BCF37F2D66EB2A009A63FD /* FTWeakPropertyContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 17BCF37C2D66EB2A009A63FD /* FTWeakPropertyContainer.h */; };
442+
17BCF3802D66EB2A009A63FD /* FTWeakPropertyContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 17BCF37D2D66EB2A009A63FD /* FTWeakPropertyContainer.m */; };
443+
17BCF3812D66EB2A009A63FD /* FTWeakPropertyContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 17BCF37C2D66EB2A009A63FD /* FTWeakPropertyContainer.h */; };
444+
17BCF3822D66EB2A009A63FD /* FTWeakPropertyContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 17BCF37C2D66EB2A009A63FD /* FTWeakPropertyContainer.h */; };
445+
17BCF3832D66EB2A009A63FD /* FTWeakPropertyContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 17BCF37D2D66EB2A009A63FD /* FTWeakPropertyContainer.m */; };
440446
17D0681A2D23F48B00D59159 /* FTTraceContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D068192D23F48B00D59159 /* FTTraceContext.m */; };
441447
17D0681B2D23F48B00D59159 /* FTTraceContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 17D068182D23F48B00D59159 /* FTTraceContext.h */; settings = {ATTRIBUTES = (Public, ); }; };
442448
17D0681C2D23F48B00D59159 /* FTTraceContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D068192D23F48B00D59159 /* FTTraceContext.m */; };
@@ -686,6 +692,8 @@
686692
17AC17422B9856C3003E18A6 /* FTFileLogger.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FTFileLogger.m; sourceTree = "<group>"; };
687693
17AC17492B98635C003E18A6 /* NSDate+FTUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDate+FTUtil.h"; sourceTree = "<group>"; };
688694
17AC174A2B98635C003E18A6 /* NSDate+FTUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDate+FTUtil.m"; sourceTree = "<group>"; };
695+
17BCF37C2D66EB2A009A63FD /* FTWeakPropertyContainer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FTWeakPropertyContainer.h; sourceTree = "<group>"; };
696+
17BCF37D2D66EB2A009A63FD /* FTWeakPropertyContainer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FTWeakPropertyContainer.m; sourceTree = "<group>"; };
689697
17D068182D23F48B00D59159 /* FTTraceContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FTTraceContext.h; sourceTree = "<group>"; };
690698
17D068192D23F48B00D59159 /* FTTraceContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FTTraceContext.m; sourceTree = "<group>"; };
691699
17D068202D26668400D59159 /* NSURLSessionTask+FTSwizzler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSURLSessionTask+FTSwizzler.h"; sourceTree = "<group>"; };
@@ -1077,6 +1085,8 @@
10771085
174BC8782BFC9F8A00478EE1 /* NSDictionary+FTCopyProperties.m */,
10781086
17F10DAB2D13C88A00737EDD /* FTNetworkConnectivity.h */,
10791087
17F10DAC2D13C88A00737EDD /* FTNetworkConnectivity.m */,
1088+
17BCF37C2D66EB2A009A63FD /* FTWeakPropertyContainer.h */,
1089+
17BCF37D2D66EB2A009A63FD /* FTWeakPropertyContainer.m */,
10801090
);
10811091
path = Base;
10821092
sourceTree = "<group>";
@@ -1284,6 +1294,7 @@
12841294
files = (
12851295
1776067F29D1370D00D17137 /* FTCallStack.h in Headers */,
12861296
1776072229D13A0F00D17137 /* NSURLSession+FTSwizzler.h in Headers */,
1297+
17BCF3822D66EB2A009A63FD /* FTWeakPropertyContainer.h in Headers */,
12871298
17E32BA52BEC70E700F4685C /* FTErrorMonitorInfo.h in Headers */,
12881299
170CD0A12AF3422000DB248C /* FTAutoInterceptorProtocol.h in Headers */,
12891300
1776072A29D13A2B00D17137 /* FTWebViewJavascriptBridgeBase.h in Headers */,
@@ -1409,6 +1420,7 @@
14091420
17AC17442B9856C3003E18A6 /* FTFileLogger.h in Headers */,
14101421
17AB76E829D432DE008FBBF5 /* FTRUMSessionHandler.h in Headers */,
14111422
17132DBF2C2D652E009DFE8F /* NSError+FTDescription.h in Headers */,
1423+
17BCF3812D66EB2A009A63FD /* FTWeakPropertyContainer.h in Headers */,
14121424
179BEB952D2D3ACC004AA5A6 /* FTSDKCompat.h in Headers */,
14131425
179BEB962D2D3ACC004AA5A6 /* FTThreadDispatchManager.h in Headers */,
14141426
177606C029D137FB00D17137 /* FTErrorDataProtocol.h in Headers */,
@@ -1588,6 +1600,7 @@
15881600
1763BD9029DFF04F009EE026 /* FTRequestBody.h in Headers */,
15891601
17E4CC3129CD42E4005C2D99 /* FTAutoTrackProperty.h in Headers */,
15901602
17AB76CC29D432DE008FBBF5 /* FTCPUMonitor.h in Headers */,
1603+
17BCF37F2D66EB2A009A63FD /* FTWeakPropertyContainer.h in Headers */,
15911604
17E4CC3029CD42E4005C2D99 /* UIApplication+FTAutoTrack.h in Headers */,
15921605
175C7D0E29E9438600A7F271 /* FTMobileAgent.h in Headers */,
15931606
1763BDA629DFF04F009EE026 /* ZY_FMResultSet.h in Headers */,
@@ -1775,6 +1788,7 @@
17751788
17AB76D429D432DE008FBBF5 /* FTMonitorItem.m in Sources */,
17761789
1763BD9B29DFF04F009EE026 /* ZY_FMResultSet.m in Sources */,
17771790
1776070829D139D800D17137 /* FTTracer.m in Sources */,
1791+
17BCF3832D66EB2A009A63FD /* FTWeakPropertyContainer.m in Sources */,
17781792
1776067229D136F800D17137 /* FTThreadDispatchManager.m in Sources */,
17791793
17E32BB02BEE21F600F4685C /* FTRUMDependencies.m in Sources */,
17801794
17AB76EF29D432DE008FBBF5 /* FTRUMResourceHandler.m in Sources */,
@@ -1867,6 +1881,7 @@
18671881
1776071B29D13A0100D17137 /* FTURLSessionDelegate.m in Sources */,
18681882
17E32BAE2BEE21F600F4685C /* FTRUMDependencies.m in Sources */,
18691883
177606FC29D1399500D17137 /* FTExtensionDataManager.m in Sources */,
1884+
17BCF3802D66EB2A009A63FD /* FTWeakPropertyContainer.m in Sources */,
18701885
17400E772B47AAB400ACBA6C /* FTNSException.m in Sources */,
18711886
1776069629D1373300D17137 /* FTJSONUtil.m in Sources */,
18721887
1776BA832B99B668008424FF /* FTOSLogger.m in Sources */,
@@ -1972,6 +1987,7 @@
19721987
17AB76D529D432DE008FBBF5 /* FTRUMMonitor.m in Sources */,
19731988
17E4CB4629CD42DA005C2D99 /* FTLog.m in Sources */,
19741989
17E4CB3F29CD42DA005C2D99 /* FTConstants.m in Sources */,
1990+
17BCF37E2D66EB2A009A63FD /* FTWeakPropertyContainer.m in Sources */,
19751991
17AB76CF29D432DE008FBBF5 /* FTMemoryMonitor.m in Sources */,
19761992
1776073929D1416200D17137 /* FTUserInfo.m in Sources */,
19771993
1776062C29D1347500D17137 /* FTWebViewJavascriptBridgeBase.m in Sources */,

FTMobileSDK/FTMobileAgent/AutoTrack/FTAutoTrackHandler.m

+58-32
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,18 @@ @interface RUMView:NSObject
2222
@property (nonatomic, copy) NSString *identify;
2323
@property (nonatomic, strong) NSNumber *loadTime;
2424
@property (nonatomic, weak) UIViewController *viewController;
25-
-(instancetype)initWithViewController:(UIViewController *)viewController;
25+
@property (nonatomic, assign) BOOL isUntrackedModal;
26+
- (instancetype)initWithViewController:(UIViewController *)viewController identify:(NSString *)identify;
2627
- (void)updateViewControllerUUID;
2728
- (NSString *)viewControllerUUID;
2829
@end
2930
@implementation RUMView
30-
-(instancetype)initWithViewController:(UIViewController *)viewController{
31+
-(instancetype)initWithViewController:(UIViewController *)viewController identify:(NSString *)identify{
3132
self = [super init];
3233
if(self){
3334
_viewName = viewController.ft_viewControllerName;
34-
_identify = [NSString stringWithFormat:@"%p", viewController];
35+
_identify = identify;
36+
_isUntrackedModal = NO;
3537
if(viewController.ft_viewUUID == nil){
3638
viewController.ft_viewUUID = [FTBaseInfoHandler randomUUID];
3739
}
@@ -149,29 +151,42 @@ -(void)applicationWillEnterForeground{
149151
}
150152
#pragma mark ========== FTUIViewControllerHandler ==========
151153
-(void)notify_viewDidAppear:(UIViewController *)viewController animated:(BOOL)animated{
152-
if(![self shouldTrackViewController:viewController]){
154+
NSString *identify = [NSString stringWithFormat:@"%p", viewController];
155+
__block RUMView *view = nil;
156+
[self.stack enumerateObjectsUsingBlock:^(RUMView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
157+
if ([obj.identify isEqualToString:identify]) {
158+
*stop = YES;
159+
view = obj;
160+
}
161+
}];
162+
if (view != nil){
163+
[self addView:view];
153164
return;
154165
}
155-
RUMView *view = [[RUMView alloc]initWithViewController:viewController];
156-
[self addView:view];
166+
if([self shouldTrackViewController:viewController]){
167+
view = [[RUMView alloc]initWithViewController:viewController identify:identify];
168+
[self addView:view];
169+
}else if (@available(iOS 13.0,tvOS 13.0, *)){
170+
if(viewController.isModalInPresentation){
171+
view = [[RUMView alloc]initWithViewController:viewController identify:identify];
172+
view.isUntrackedModal = YES;
173+
[self addView:view];
174+
}
175+
}
157176
}
158177
-(void)notify_viewDidDisappear:(UIViewController *)viewController animated:(BOOL)animated{
159-
if(![self shouldTrackViewController:viewController]){
160-
return;
161-
}
162-
[self removeView:viewController viewControllerUUID:viewController.ft_viewUUID];
178+
[self removeView:viewController];
163179
}
164180
- (void)addView:(RUMView *)view{
165181
if([[self.stack lastObject].identify isEqualToString:view.identify]){
166182
return;
167183
}
168184
if ([self.stack lastObject]) {
169-
// 没有从数组中移除的原因是有一些特殊视图,比如模态视图添加到window时,原有的 VC 并不会调用 didDisappear 方法,当这些特殊视图移除时,原有的 VC 也不会调用 DidAppear 方法,所以需要保留,重新添加到 RUM View。
185+
// 没有从数组中移除的原因是有一些特殊视图,比如模态视图添加到 window 时,或者新的 window 添加到窗口,window 上有 VC,原有的 VC 并不会调用 didDisappear 方法,当这些特殊视图移除时,原有的 VC 也不会调用 DidAppear 方法,所以需要保留,重新添加到 RUM View。
170186
RUMView *current = [self.stack lastObject];
171-
[self.addRumDatasDelegate stopViewWithViewID:current.identify property:nil];
187+
[self stopView:current];
172188
}
173-
[self.addRumDatasDelegate onCreateView:view.viewName loadTime:view.loadTime];
174-
[self.addRumDatasDelegate startViewWithViewID:view.viewControllerUUID viewName:view.viewName property:nil];
189+
[self startView:view];
175190

176191
[self.stack enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(RUMView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
177192
if([obj.identify isEqualToString:view.identify]){
@@ -180,7 +195,7 @@ - (void)addView:(RUMView *)view{
180195
}];
181196
[self.stack addObject:view];
182197
}
183-
- (void)removeView:(UIViewController *)viewController viewControllerUUID:(NSString *)viewControllerUUID{
198+
- (void)removeView:(UIViewController *)viewController{
184199
NSString *identify = [NSString stringWithFormat:@"%p", viewController];
185200
if(![[self.stack lastObject].identify isEqualToString:identify]){
186201
[self.stack enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(RUMView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
@@ -190,28 +205,39 @@ - (void)removeView:(UIViewController *)viewController viewControllerUUID:(NSStri
190205
}];
191206
return;
192207
}
193-
[self.stack removeLastObject];
194-
[self.addRumDatasDelegate stopViewWithViewID:viewControllerUUID property:nil];
208+
RUMView *stopView = [self.stack lastObject];
209+
if(stopView){
210+
[self.stack removeLastObject];
211+
[self stopView:stopView];
212+
}
195213

196-
if([self.stack lastObject]){
197-
RUMView *current = [self.stack lastObject];
198-
[current updateViewControllerUUID];
199-
[self.addRumDatasDelegate startViewWithViewID:current.viewControllerUUID viewName:current.viewName property:nil];
214+
RUMView *reStartView = [self.stack lastObject];
215+
if(reStartView){
216+
[reStartView updateViewControllerUUID];
217+
[self startView:reStartView];
200218
}
201219
}
202-
- (BOOL)shouldTrackViewController:(UIViewController *)viewController{
203-
if([viewController isBlackListContainsViewController]){
204-
return NO;
220+
- (void)startView:(RUMView *)view{
221+
if(!self.addRumDatasDelegate){
222+
return;
205223
}
206-
UIViewController *parent = viewController.parentViewController;
207-
while (parent != nil) {
208-
if ([parent isKindOfClass:UIPageViewController.class] || [parent isKindOfClass:UISplitViewController.class]) {
209-
return NO;
210-
}else{
211-
parent = parent.parentViewController;
212-
}
224+
// 确保黑名单视图,不会影响采集视图的 duration
225+
// 黑名单视图模态弹出时,关闭上一个采集的 View,关闭时,重新开启上一个 View 采集
226+
if(!view.isUntrackedModal){
227+
[self.addRumDatasDelegate onCreateView:view.viewName loadTime:view.loadTime];
228+
[self.addRumDatasDelegate startViewWithViewID:view.viewControllerUUID viewName:view.viewName property:nil];
229+
}
230+
}
231+
- (void)stopView:(RUMView *)view{
232+
if(!self.addRumDatasDelegate){
233+
return;
234+
}
235+
if(!view.isUntrackedModal){
236+
[self.addRumDatasDelegate stopViewWithViewID:view.viewControllerUUID property:nil];
213237
}
214-
return YES;
238+
}
239+
- (BOOL)shouldTrackViewController:(UIViewController *)viewController{
240+
return ![viewController isBlackListContainsViewController];
215241
}
216242
-(void)shutDown{
217243
self.stack = nil;

FTMobileSDK/FTMobileAgent/AutoTrack/UIViewController+FTAutoTrack.h

+7
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,17 @@ NS_ASSUME_NONNULL_BEGIN
1212

1313
@interface UIViewController (FTAutoTrack)<FTRumViewProperty>
1414
-(BOOL)isBlackListContainsViewController;
15+
- (BOOL)isActionBlackListContainsViewController;
1516
-(NSString *)ft_viewControllerName;
1617
-(void)ft_viewDidLoad;
1718
-(void)ft_viewDidAppear:(BOOL)animated;
1819
-(void)ft_viewDidDisappear:(BOOL)animated;
1920
@end
2021

22+
@interface UINavigationController (FTAutoTrack)
23+
24+
/// 上一次页面,防止侧滑/下滑重复采集 View 事件
25+
@property (nonatomic, strong,nullable) UIViewController *ft_previousViewController;
26+
27+
@end
2128
NS_ASSUME_NONNULL_END

FTMobileSDK/FTMobileAgent/AutoTrack/UIViewController+FTAutoTrack.m

+35-11
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616
#import "FTAutoTrackHandler.h"
1717
#import "NSDate+FTUtil.h"
1818
#import "FTBaseInfoHandler.h"
19+
#import "FTWeakPropertyContainer.h"
20+
1921
static char *viewLoadStartTimeKey = "viewLoadStartTimeKey";
2022
static char *viewControllerUUID = "viewControllerUUID";
2123
static char *viewLoadDuration = "viewLoadDuration";
24+
static char *previousViewController = "previousViewController";
2225

2326
@implementation UIViewController (FTAutoTrack)
2427
-(void)setFt_viewLoadStartTime:(NSDate*)viewLoadStartTime{
@@ -80,22 +83,43 @@ - (void)ft_viewDidLoad{
8083
}
8184
-(void)ft_viewDidAppear:(BOOL)animated{
8285
[self ft_viewDidAppear:animated];
83-
[[FTAutoTrackHandler sharedInstance].viewControllerHandler notify_viewDidAppear:self animated:animated];
86+
// 防止 tabbar 切换,可能漏采 startView 全埋点
87+
if ([self isKindOfClass:UINavigationController.class]) {
88+
UINavigationController *nav = (UINavigationController *)self;
89+
nav.ft_previousViewController = nil;
90+
}
91+
if (self.navigationController && self.parentViewController == self.navigationController) {
92+
// 忽略由于侧滑部分返回原页面,重复触发 startView 事件
93+
if (self.navigationController.ft_previousViewController == self) {
94+
return;
95+
}
96+
}
97+
if (!self.parentViewController ||
98+
[self.parentViewController isKindOfClass:[UITabBarController class]] ||
99+
[self.parentViewController isKindOfClass:[UINavigationController class]] ||
100+
[self.parentViewController isKindOfClass:[UIPageViewController class]] ||
101+
[self.parentViewController isKindOfClass:[UISplitViewController class]]) {
102+
[[FTAutoTrackHandler sharedInstance].viewControllerHandler notify_viewDidAppear:self animated:animated];
103+
}
104+
// 标记 previousViewController
105+
if (self.navigationController && self.parentViewController == self.navigationController) {
106+
self.navigationController.ft_previousViewController = self;
107+
}
84108
}
85109
-(void)ft_viewDidDisappear:(BOOL)animated{
86110
[self ft_viewDidDisappear:animated];
87111
[[FTAutoTrackHandler sharedInstance].viewControllerHandler notify_viewDidDisappear:self animated:animated];
88112
}
113+
@end
114+
@implementation UINavigationController (FTAutoTrack)
89115

90-
-(BOOL)ft_parentViewControllerIsContainer{
91-
UIViewController *parent = self.parentViewController;
92-
while (parent != nil) {
93-
if ([parent isKindOfClass:UIPageViewController.class] || [parent isKindOfClass:UISplitViewController.class]) {
94-
return YES;
95-
}else{
96-
parent = parent.parentViewController;
97-
}
98-
}
99-
return NO;
116+
- (void)setFt_previousViewController:(UIViewController *)ft_previousViewController {
117+
FTWeakPropertyContainer *container = [FTWeakPropertyContainer containerWithWeakProperty:ft_previousViewController];
118+
objc_setAssociatedObject(self, previousViewController, container, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
100119
}
120+
- (UIViewController *)ft_previousViewController {
121+
FTWeakPropertyContainer *container = objc_getAssociatedObject(self, previousViewController);
122+
return container.weakProperty;
123+
}
124+
101125
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//
2+
// FTWeakPropertyContainer.h
3+
// FTMobileSDK
4+
//
5+
// Created by hulilei on 2025/2/20.
6+
// Copyright © 2025 DataFlux-cn. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
11+
NS_ASSUME_NONNULL_BEGIN
12+
13+
@interface FTWeakPropertyContainer : NSObject
14+
@property (readonly, nonatomic, weak) id weakProperty;
15+
16+
+ (instancetype)containerWithWeakProperty:(id)weakProperty;
17+
@end
18+
19+
NS_ASSUME_NONNULL_END
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// FTWeakPropertyContainer.m
3+
// FTMobileSDK
4+
//
5+
// Created by hulilei on 2025/2/20.
6+
// Copyright © 2025 DataFlux-cn. All rights reserved.
7+
//
8+
9+
#import "FTWeakPropertyContainer.h"
10+
@interface FTWeakPropertyContainer()
11+
@property (nonatomic, weak) id weakProperty;
12+
13+
@end
14+
15+
@implementation FTWeakPropertyContainer
16+
17+
+ (instancetype)containerWithWeakProperty:(id)weakProperty {
18+
FTWeakPropertyContainer *container = [[FTWeakPropertyContainer alloc]init];
19+
container.weakProperty = weakProperty;
20+
return container;
21+
}
22+
@end

0 commit comments

Comments
 (0)