Skip to content

Commit

Permalink
Release 4.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
王洋洋 committed Nov 18, 2022
1 parent 881e178 commit 13d0c06
Show file tree
Hide file tree
Showing 37 changed files with 1,078 additions and 404 deletions.
2 changes: 1 addition & 1 deletion SensorsAnalyticsSDK.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "SensorsAnalyticsSDK"
s.version = "4.4.8"
s.version = "4.5.0"
s.summary = "The official iOS SDK of Sensors Analytics."
s.homepage = "http://www.sensorsdata.cn"
s.source = { :git => 'https://github.com/sensorsdata/sa-sdk-ios.git', :tag => "v#{s.version}" }
Expand Down
82 changes: 50 additions & 32 deletions SensorsAnalyticsSDK.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion SensorsAnalyticsSDK/Core/SAConstants+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ extern NSNotificationName const SA_H5_MESSAGE_NOTIFICATION;
#pragma mark - SA notifications
extern NSNotificationName const SA_REMOTE_CONFIG_MODEL_CHANGED_NOTIFICATION;

extern NSNotificationName const SA_VISUALIZED_H5_MESSAGE_NOTIFICATION;
/// 接收 App 内嵌 H5 可视化相关页面元素信息
extern NSNotificationName const kSAVisualizedMessageFromH5Notification;

// page leave
extern NSString * const kSAEventDurationProperty;
Expand Down
4 changes: 2 additions & 2 deletions SensorsAnalyticsSDK/Core/SAConstants.m
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ void sensorsdata_dispatch_safe_sync(dispatch_queue_t queue,DISPATCH_NOESCAPE dis
// 远程配置更新
NSNotificationName const SA_REMOTE_CONFIG_MODEL_CHANGED_NOTIFICATION = @"cn.sensorsdata.SA_REMOTE_CONFIG_MODEL_CHANGED_NOTIFICATION";

// App 内嵌 H5 接收可视化相关 H5 页面元素信息
NSNotificationName const SA_VISUALIZED_H5_MESSAGE_NOTIFICATION = @"SensorsAnalyticsVisualizedMessageFromH5Notification";
// 接收 App 内嵌 H5 可视化相关页面元素信息
NSNotificationName const kSAVisualizedMessageFromH5Notification = @"SensorsAnalyticsVisualizedMessageFromH5Notification";

//page leave
NSString * const kSAEventDurationProperty = @"event_duration";
Expand Down
15 changes: 10 additions & 5 deletions SensorsAnalyticsSDK/Core/SAModuleManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ @implementation SAModuleManager

+ (void)startWithConfigOptions:(SAConfigOptions *)configOptions {
SAModuleManager.sharedInstance.configOptions = configOptions;
// 禁止 SDK 时,不开启其他模块
if (configOptions.disableSDK) {
return;
}
[[SAModuleManager sharedInstance] loadModulesWithConfigOptions:configOptions];
}

Expand Down Expand Up @@ -99,6 +95,10 @@ - (id)moduleWithName:(NSString *)moduleName {
// module加载
- (void)loadModulesWithConfigOptions:(SAConfigOptions *)configOptions {
[self loadModule:kSAJavaScriptBridgeModuleName withConfigOptions:configOptions];
// 禁止 SDK 时,不开启其他模块
if (configOptions.disableSDK) {
return;
}
#if TARGET_OS_IOS
for (NSString *moduleName in self.moduleNames) {
if ([moduleName isEqualToString:kSAJavaScriptBridgeModuleName]) {
Expand Down Expand Up @@ -429,7 +429,12 @@ - (NSString *)javaScriptSource {
if ([module conformsToProtocol:@protocol(SAJavaScriptBridgeModuleProtocol)] && [module respondsToSelector:@selector(javaScriptSource)] && [module conformsToProtocol:@protocol(SAModuleProtocol)]) {
id<SAJavaScriptBridgeModuleProtocol, SAModuleProtocol>moduleObject = module;
NSString *javaScriptSource = [moduleObject javaScriptSource];
moduleObject.isEnable && javaScriptSource.length > 0 ? [source appendString:javaScriptSource] : nil;
if (javaScriptSource.length <= 0) {
continue;
}
if ([moduleName isEqualToString:kSAJavaScriptBridgeModuleName] || moduleObject.isEnable) {
[source appendString:javaScriptSource];
}
}
}
return source;
Expand Down
2 changes: 1 addition & 1 deletion SensorsAnalyticsSDK/Core/SensorsAnalyticsSDK.m
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
#import "SALimitKeyManager.h"
#import "NSDictionary+SACopyProperties.h"

#define VERSION @"4.4.8"
#define VERSION @"4.5.0"

void *SensorsAnalyticsQueueTag = &SensorsAnalyticsQueueTag;

Expand Down
4 changes: 2 additions & 2 deletions SensorsAnalyticsSDK/Core/Utils/SACommonUtility.m
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ + (NSString *)hashStringWithData:(NSData *)data {
在 iOS 中 NSData 的 hash 实现,仅使用数据的前 80 个字节来计算哈希,参考:https://opensource.apple.com/source/CF/CF-635.21/CFData.c
*/
NSString *base64String = [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
NSUInteger hash = [base64String hash];
return [NSString stringWithFormat:@"%ld",hash];
NSNumber *hashNumber = [NSNumber numberWithUnsignedInteger:[base64String hash]];
return [hashNumber stringValue];
}

@end
6 changes: 1 addition & 5 deletions SensorsAnalyticsSDK/JSBridge/SAJavaScriptBridgeManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,6 @@ - (void)swizzleWebViewMethod {
}

- (void)addScriptMessageHandlerWithWebView:(WKWebView *)webView {
if ([SAModuleManager.sharedInstance isDisableSDK]) {
return;
}

NSAssert([webView isKindOfClass:[WKWebView class]], @"This injection solution only supports WKWebView! ❌");
if (![webView isKindOfClass:[WKWebView class]]) {
return;
Expand Down Expand Up @@ -192,7 +188,7 @@ - (void)userContentController:(WKUserContentController *)userContentController d
app_alert:H5 弹框信息,提示配置错误信息;
page_info:H5 页面信息,包括 url、title 和 lib_version
*/
[[NSNotificationCenter defaultCenter] postNotificationName:SA_VISUALIZED_H5_MESSAGE_NOTIFICATION object:message];
[[NSNotificationCenter defaultCenter] postNotificationName:kSAVisualizedMessageFromH5Notification object:message];
} else if ([callType isEqualToString:@"abtest"]) {
// 通知 SensorsABTest,接收到 H5 的请求数据
[[NSNotificationCenter defaultCenter] postNotificationName:SA_H5_MESSAGE_NOTIFICATION object:message];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@
"key": "is_list_view",
"type": "BOOL",
"use_kvc": false
},
{
"name": "sensorsdata_platform",
"key": "element_platform",
"type": "NSString",
"use_kvc": false
}
]
},
Expand Down Expand Up @@ -136,6 +142,10 @@
}
]
},
{
"name": "SAFlutterElementView",
"superclass": "UIView"
},
{
"name": "UIScrollView",
"superclass": "UIView",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,29 @@
"SADebugNotes" = "SensorsData 重要提示";

// 可视化全埋点
"SAVisualizedAutoTrack" = "可视化全埋点";
"SAVisualizedPageErrorTitle" = "当前页面无法进行可视化全埋点";
"SAVisualizedConfigurationDocument" = "配置文档";
"SAVisualizedConnect" = "正在连接 App 可视化全埋点";
"SAVisualizedWifi" = ",建议在 WiFi 环境下使用";
"SAVisualizedProjectError" = "App 集成的项目与电脑浏览器打开的项目不同,无法进行可视化全埋点";
"SAVisualizedEnableLogHint" = "可视化全埋点进入 Debug 模式,需要开启日志打印用于收集调试信息,退出 Debug 模式关闭日志打印,是否需要开启呢?";
"SAVisualizedEnableLogAction" = "开启日志打印";
"SAVisualizedTemporarilyDisabled" = "暂不开启";
"SAVisualizedPageErrorTitle" = "当前页面无法进行可视化全埋点";
"SAVisualizedPageErrorMessage" = "此页面不是 WKWebView,iOS App 内嵌 H5 可视化全埋点,只支持 WKWebView";
"SAVisualizedConfigurationDocument" = "配置文档";
"SAVisualizedWebPageErrorMessage" = "此页面不是 WKWebView,iOS App 内嵌 H5 可视化全埋点,只支持 WKWebView";
"SAVisualizedJSError" = "此页面未集成 Web JS SDK 或者 Web JS SDK 版本过低,请集成最新版 Web JS SDK";
"SAVisualizedSDKError" = "SDK 没有被正确集成,请联系贵方技术人员开启可视化全埋点";
"SAVisualizedParameterError" = "参数错误";
"SAVisualizedAutoTrack" = "可视化全埋点";
// Flutter 可视化
"SAVisualizedFlutterPageErrorMessage" = "此页面未集成 Flutter 全埋点 SDK 或 Flutter 全埋点 SDK 版本过低,请集成最新版 Flutter 全埋点 SDK";


// 点击分析
"SAAppClicksAnalyticsConnect" = "正在连接 App 点击分析";
"SAAppClicksAnalyticsSDKError" = "SDK 没有被正确集成,请联系贵方技术人员开启点击分析";
"SAAppClicksAnalyticsProjectError" = "App 集成的项目与电脑浏览器打开的项目不同,无法进行点击分析";
"SAAppClicksAnalyticsPageErrorTitle" = "当前页面无法进行点击分析";
"SAAppClicksAnalyticsPageErrorMessage" = "此页面包含 UIWebView,iOS App 内嵌 H5 点击分析,只支持 WKWebView";
"SAAppClicksAnalyticsPageWebErrorMessage" = "此页面包含 UIWebView,iOS App 内嵌 H5 点击分析,只支持 WKWebView";
"SAAppClicksAnalytics" = "点击分析";

// 远程配置
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,13 @@ - (void)requestConfigWithTimes:(NSInteger)times {
}

- (void)requestConfigWithCompletionHandler:(SAVisualPropertiesConfigCompletionHandler)completionHandler {

if (![SAReachability sharedInstance].reachable) {
SALogWarn(@"The current network is unavailable, please check the network !");
completionHandler(NO, nil);
return;
}

// SAReachability 同步网络判断存在延迟,冷启动后立即判断,可能误判为 NO
// if (![SAReachability sharedInstance].reachable) {
// SALogWarn(@"The current network is unavailable, please check the network !");
// completionHandler(NO, nil);
// return;
// }

// 拼接请求参数
NSURLRequest *request = [self buildConfigRequest];
Expand All @@ -150,7 +151,7 @@ - (void)requestConfigWithCompletionHandler:(SAVisualPropertiesConfigCompletionHa
NSURLSessionDataTask *task = [SAHTTPSession.sharedInstance dataTaskWithRequest:request completionHandler:^(NSData *_Nullable data, NSHTTPURLResponse *_Nullable response, NSError *_Nullable error) {
NSInteger statusCode = response.statusCode;
/* statusCode 说明
200:正常请求并正确返回配置
200:正常请求并正确返回配置,或删除全部可视化全埋点事件(events 字段为空数组)
304:如果本地配置和后端最新版本相同,则返回 304,同时配置为空
205:配置不存在(未创建可视化全埋点事件或运维关闭自定义属性),此时配置为空,返回 205
404:当前环境未包含此接口,可能 SA 版本比较低,暂不支持自定义属性
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@
/// 是否为列表(本身支持限定位置,比如 Cell)
@property (nonatomic, assign) BOOL sensorsdata_isListView;

/// 元素所在平台
///
/// 区分不同平台的元素(ios/h5/flutter),Flutter 和其他平台,不支持混合圈选(事件和属性元素属于不同平台),需要给予屏蔽
@property (nonatomic, copy) NSString *sensorsdata_platform;


@end

#pragma mark - Extension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,20 @@ NS_ASSUME_NONNULL_BEGIN

@end

@interface UIScrollView (SAVisualizedViewPath)<SAVisualizedExtensionProperty>
@end

@interface WKWebView (SAVisualizedViewPath)<SAVisualizedViewPathProperty>

@end

@interface UIWindow (SAVisualizedViewPath)<SAVisualizedViewPathProperty>
@end

/// 其他平台的构造可视化页面元素
@interface SAVisualizedElementView (SAElementPath)<SAVisualizedViewPathProperty>
@end

/// App 内嵌 H5 页面元素信息
@interface SAWebElementView (SAElementPath)<SAVisualizedViewPathProperty>

@end

#pragma mark - UIControl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,18 @@ - (NSArray *)sensorsdata_subElements {
if ([SAVisualizedUtils isIgnoreSubviewsWithView:self]) {
return nil;
}

NSMutableArray *newSubViews = [NSMutableArray array];

// 构建 flutter 元素
// flutter 页面判断
if (NSClassFromString(@"FlutterView") && [self isKindOfClass:NSClassFromString(@"FlutterView")]) {
// FlutterView 上可能嵌套 Native 元素或 webView
NSArray *subElements = [SAVisualizedUtils analysisFlutterElementWithFlutterView:self];
if (subElements.count > 0) {
[newSubViews addObjectsFromArray:subElements];
}
}

/* 特殊场景兼容
controller1.vew 上直接添加 controller2.view,
Expand All @@ -248,8 +260,7 @@ - (NSArray *)sensorsdata_subElements {
return controller.sensorsdata_subElements;
}
}

NSMutableArray *newSubViews = [NSMutableArray array];

NSArray<UIView *>* subViews = self.subviews;
// 针对 RCTView,获取按照 zIndex 排序后的子元素
if ([SAVisualizedUtils isKindOfRCTView:self]) {
Expand All @@ -275,6 +286,10 @@ - (BOOL)sensorsdata_isListView {
return NO;
}

- (NSString *)sensorsdata_platform {
return @"ios";
}

- (NSString *)sensorsdata_screenName {
// 解析 ReactNative 元素页面名称
if ([self isSensorsdataRNView]) {
Expand Down Expand Up @@ -325,6 +340,13 @@ - (CGRect)sensorsdata_frame {

- (CGRect)sensorsdata_visibleFrame {
CGRect visibleFrame = [UIApplication sharedApplication].keyWindow.frame;
/* 如果 clipsToBounds = YES,剪裁超出父视图范围的子视图部分,即子视图超出父视图部分不可见
UIScrollView 中,它的默认值是 YES,也就是说默认裁剪的
所以 clipsToBounds = YES,当前视图的可见有效范围只有自身尺寸
*/
if (self.clipsToBounds) {
visibleFrame = [self convertRect:self.bounds toView:nil];
}
if (self.superview) {
CGRect superViewVisibleFrame = [self.superview sensorsdata_visibleFrame];
visibleFrame = CGRectIntersection(visibleFrame, superViewVisibleFrame);
Expand All @@ -342,24 +364,6 @@ - (void)setSensorsdata_isDisableRNSubviewsInteractive:(BOOL)sensorsdata_isDisabl

@end


@implementation UIScrollView (SAVisualizedViewPath)

- (CGRect)sensorsdata_visibleFrame {
CGRect showRect = [self convertRect:self.bounds toView:nil];
if (self.superview) {
/* UIScrollView 单独处理
UIScrollView 上子元素超出父视图部分不可见。
普通 UIView 超出父视图,依然显示,但是超出部分不可交互,除非实现 hitTest
*/
CGRect superViewValidFrame = [self.superview sensorsdata_visibleFrame];
showRect = CGRectIntersection(showRect, superViewValidFrame);
}
return showRect;
}

@end

@implementation WKWebView (SAVisualizedViewPath)

- (NSArray *)sensorsdata_subElements {
Expand Down Expand Up @@ -409,15 +413,15 @@ - (NSArray *)sensorsdata_subElements {

@end

@implementation SAWebElementView (SAVisualizedViewPath)
@implementation SAVisualizedElementView (SAElementPath)

#pragma mark SAVisualizedViewPathProperty
- (NSString *)sensorsdata_title {
return self.title;
}

- (NSString *)sensorsdata_elementSelector {
return self.elementSelector;
- (NSString *)sensorsdata_screenName {
return self.screenName;
}

- (NSString *)sensorsdata_elementValidContent {
Expand All @@ -433,20 +437,24 @@ - (BOOL)sensorsdata_enableAppClick {
}

- (NSArray *)sensorsdata_subElements {
if (self.jsSubviews.count > 0) {
return self.jsSubviews;
if (self.subElements.count > 0) {
return self.subElements;
}
return [super sensorsdata_subElements];
}

- (BOOL)sensorsdata_isFromWeb {
return YES;
return NO;
}

- (BOOL)sensorsdata_isListView {
return self.isListView;
}

- (NSString *)sensorsdata_platform {
return self.platform;
}

- (NSString *)sensorsdata_elementPath {
return self.elementPath;
}
Expand All @@ -457,6 +465,18 @@ - (NSString *)sensorsdata_elementPosition {

@end


@implementation SAWebElementView (SAElementPath)
- (BOOL)sensorsdata_isFromWeb {
return YES;
}

- (NSString *)sensorsdata_elementSelector {
return self.elementSelector;
}

@end

#pragma mark - UIControl
@implementation UISwitch (SAVisualizedViewPath)

Expand Down
Loading

0 comments on commit 13d0c06

Please sign in to comment.