diff --git a/SensorsAnalyticsSDK.podspec b/SensorsAnalyticsSDK.podspec index 24343c2c..38542e1e 100644 --- a/SensorsAnalyticsSDK.podspec +++ b/SensorsAnalyticsSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "SensorsAnalyticsSDK" - s.version = "4.5.21" + s.version = "4.5.22" 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}" } diff --git a/SensorsAnalyticsSDK/Core/Builder/EventObject/SABaseEventObject.m b/SensorsAnalyticsSDK/Core/Builder/EventObject/SABaseEventObject.m index df88077e..a1265daf 100644 --- a/SensorsAnalyticsSDK/Core/Builder/EventObject/SABaseEventObject.m +++ b/SensorsAnalyticsSDK/Core/Builder/EventObject/SABaseEventObject.m @@ -51,7 +51,6 @@ - (instancetype)initWithH5Event:(NSDictionary *)event { NSString *type = event[kSAEventType]; _type = [SABaseEventObject eventTypeWithType:type]; _lib = [[SAEventLibObject alloc] initWithH5Lib:event[kSAEventLib]]; - _time = [[NSDate date] timeIntervalSince1970] * 1000; _trackId = @(arc4random()); _currentSystemUpTime = NSProcessInfo.processInfo.systemUptime * 1000; @@ -59,6 +58,12 @@ - (instancetype)initWithH5Event:(NSDictionary *)event { _hybridH5 = YES; + // 优先使用 web 端时间,防止历史事件时间被改错 + if ([event[kSAEventTime] isKindOfClass:NSNumber.class]) { + _time = [event[kSAEventTime] unsignedLongLongValue]; + } else { + _time = [[NSDate date] timeIntervalSince1970] * 1000; + } _eventId = event[kSAEventName]; _loginId = event[kSAEventLoginId]; _anonymousId = event[kSAEventAnonymousId]; @@ -72,21 +77,18 @@ - (instancetype)initWithH5Event:(NSDictionary *)event { _token = properties[kSAEventToken]; id timeNumber = properties[kSAEventCommonOptionalPropertyTime]; - if (timeNumber) { //包含 $time - NSNumber *customTime = nil; - if ([timeNumber isKindOfClass:[NSDate class]]) { - customTime = @([(NSDate *)timeNumber timeIntervalSince1970] * 1000); - } else if ([timeNumber isKindOfClass:[NSNumber class]]) { - customTime = timeNumber; - } + // $time 类型合法 + if ([timeNumber isKindOfClass:[NSNumber class]]) { + NSNumber *customTime = timeNumber; - if (!customTime) { - SALogError(@"H5 $time '%@' invalid,Please check the value", timeNumber); - } else if ([customTime compare:@(kSAEventCommonOptionalPropertyTimeInt)] == NSOrderedAscending) { + if ([customTime compare:@(kSAEventCommonOptionalPropertyTimeInt)] == NSOrderedAscending) { SALogError(@"H5 $time error %@,Please check the value", timeNumber); } else { _time = [customTime unsignedLongLongValue]; } + } else if (timeNumber) { + // $time 类型不合法 + SALogError(@"H5 $time '%@' invalid,Please check the value", timeNumber); } [properties removeObjectsForKeys:@[@"_nocache", @"server_url", kSAAppVisualProperties, kSAEventProject, kSAEventToken, kSAEventCommonOptionalPropertyTime]]; diff --git a/SensorsAnalyticsSDK/Core/Interceptor/EventBuild/SAPropertyInterceptor.m b/SensorsAnalyticsSDK/Core/Interceptor/EventBuild/SAPropertyInterceptor.m index 6851d495..69c560af 100644 --- a/SensorsAnalyticsSDK/Core/Interceptor/EventBuild/SAPropertyInterceptor.m +++ b/SensorsAnalyticsSDK/Core/Interceptor/EventBuild/SAPropertyInterceptor.m @@ -59,8 +59,8 @@ - (void)processWithInput:(SAFlowData *)input completion:(SAFlowDataCompletion)co object.token = (NSString *)properties[kSAEventCommonOptionalPropertyToken]; id originalTime = properties[kSAEventCommonOptionalPropertyTime]; - // App 内嵌 H5 自定义 time 在初始化中单独处理 - if ([originalTime isKindOfClass:NSDate.class] && !object.hybridH5) { + // 如果公共属性设置 $time, H5 事件也需要修改 + if ([originalTime isKindOfClass:NSDate.class]) { NSDate *customTime = (NSDate *)originalTime; int64_t customTimeInt = [customTime timeIntervalSince1970] * 1000; if (customTimeInt >= kSAEventCommonOptionalPropertyTimeInt) { @@ -68,7 +68,7 @@ - (void)processWithInput:(SAFlowData *)input completion:(SAFlowDataCompletion)co } else { SALogError(@"$time error %lld, Please check the value", customTimeInt); } - } else if (originalTime && !object.hybridH5) { + } else if (originalTime) { SALogError(@"$time '%@' invalid, Please check the value", originalTime); } diff --git a/SensorsAnalyticsSDK/Core/SALogger/SAConsoleLogger.m b/SensorsAnalyticsSDK/Core/SALogger/SAConsoleLogger.m index 0e541595..7bd33eb3 100644 --- a/SensorsAnalyticsSDK/Core/SALogger/SAConsoleLogger.m +++ b/SensorsAnalyticsSDK/Core/SALogger/SAConsoleLogger.m @@ -44,10 +44,9 @@ - (NSString *)sensorsdata_unicodeString { [mutableString appendString:@"\""]; NSData *data = [mutableString dataUsingEncoding:NSUTF8StringEncoding]; - NSError *error = nil; NSPropertyListFormat format = NSPropertyListOpenStepFormat; - NSString *formatString = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:&format error:&error]; - return error ? self : [formatString stringByReplacingOccurrencesOfString:@"\\r\\n" withString:@"\n"]; + NSString *formatString = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:&format error:NULL]; + return (!formatString || ![formatString isKindOfClass:NSString.class]) ? self : [formatString stringByReplacingOccurrencesOfString:@"\\r\\n" withString:@"\n"]; } @end diff --git a/SensorsAnalyticsSDK/Core/SensorsAnalyticsSDK.m b/SensorsAnalyticsSDK/Core/SensorsAnalyticsSDK.m index 5289af8d..710f0f43 100755 --- a/SensorsAnalyticsSDK/Core/SensorsAnalyticsSDK.m +++ b/SensorsAnalyticsSDK/Core/SensorsAnalyticsSDK.m @@ -64,7 +64,7 @@ #import "SALimitKeyManager.h" #import "NSDictionary+SACopyProperties.h" -#define VERSION @"4.5.21" +#define VERSION @"4.5.22" void *SensorsAnalyticsQueueTag = &SensorsAnalyticsQueueTag; @@ -974,12 +974,22 @@ - (void)increment:(NSDictionary *)profileDict { } - (void)append:(NSString *)profile by:(NSObject *)content { - if (profile && content) { - if ([content isKindOfClass:[NSSet class]] || [content isKindOfClass:[NSArray class]]) { - SAProfileAppendEventObject *object = [[SAProfileAppendEventObject alloc] initWithType:kSAProfileAppend]; - - [self trackEventObject:object properties:@{profile: content}]; - } + if (!profile || !content) { + SALogWarn(@"content and profile cannot be empty, please check the value"); + return; + } + if (![content isKindOfClass:NSArray.class] && ![content isKindOfClass:NSSet.class]) { + SALogWarn(@"content values should be NSArray or NSSet class, but current value: %@, with invalid type: %@", content, [content class]); + return; + } + + SAProfileAppendEventObject *object = [[SAProfileAppendEventObject alloc] initWithType:kSAProfileAppend]; + // 针对 NSArray 元素去重 + if ([content isKindOfClass:NSArray.class]) { + NSSet *uniqueSet = [NSSet setWithArray:(NSArray *)content]; + [self trackEventObject:object properties:@{profile: uniqueSet}]; + } else { + [self trackEventObject:object properties:@{profile: content}]; } } diff --git a/SensorsAnalyticsSDK/Location/SALocationManager.m b/SensorsAnalyticsSDK/Location/SALocationManager.m index ed1c1d7a..0a529f4c 100644 --- a/SensorsAnalyticsSDK/Location/SALocationManager.m +++ b/SensorsAnalyticsSDK/Location/SALocationManager.m @@ -30,6 +30,10 @@ static NSString * const kSAEventPresetPropertyLatitude = @"$latitude"; static NSString * const kSAEventPresetPropertyLongitude = @"$longitude"; static NSString * const kSAEventPresetPropertyCoordinateSystem = @"$geo_coordinate_system"; + +/* 国际通用的地球坐标系,CLLocationManager 采集定位输出结果是 WGS-84 坐标 + 国内地图,比如高德、腾讯等,因为国家的保密要求,使用的是偏移后 GCJ-02坐标,戏称“火星坐标”,和 WGS84 存在坐标偏差 + */ static NSString * const kSAAppleCoordinateSystem = @"WGS84"; @interface SALocationManager() diff --git a/SensorsAnalyticsSDK/Visualized/WebElementInfo/SAVisualizedElementView.h b/SensorsAnalyticsSDK/Visualized/WebElementInfo/SAVisualizedElementView.h index df871a3e..4213ecf1 100644 --- a/SensorsAnalyticsSDK/Visualized/WebElementInfo/SAVisualizedElementView.h +++ b/SensorsAnalyticsSDK/Visualized/WebElementInfo/SAVisualizedElementView.h @@ -61,7 +61,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) NSInteger level; /// 元素平台 -@property (nonatomic, assign) NSString *platform; +@property (nonatomic, copy) NSString *platform; @end