Skip to content

Commit

Permalink
Release 1.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
王洋洋 committed May 12, 2023
1 parent 7cea80d commit 092f667
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 38 deletions.
14 changes: 2 additions & 12 deletions Example/Example-iOS/ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
case 0: { // INTEGER
id result = [[SensorsABTest sharedInstance] fetchCacheABTestWithParamName:@"color1" defaultValue:@(1111)];
NSLog(@"fetchCacheABTest,paramName:%@ - result:%@\n", @"color1", result);

// id result2 = [[SensorsABTest sharedInstance] fetchCacheABTestWithParamName:@"102" defaultValue:@(1111)];
// NSLog(@"fetchCacheABTest,paramName:%@ - result:%@\n", @"102", result2);
}
break;

Expand Down Expand Up @@ -83,10 +80,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
[[SensorsABTest sharedInstance] asyncFetchABTestWithParamName:@"color1" defaultValue:@(1111) completionHandler:^(id _Nullable result) {
NSLog(@"asyncFetchABTest,paramName:%@ - result:%@\n", @"color1", result);
}];

[[SensorsABTest sharedInstance] asyncFetchABTestWithParamName:@"19" defaultValue:@(1111) completionHandler:^(id _Nullable result) {
NSLog(@"asyncFetchABTest,paramName:%@ - result:%@\n", @"19", result);
}];
}
break;

Expand Down Expand Up @@ -123,9 +116,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
NSLog(@"fastFetchABTest,paramName:%@ - result:%@\n", @"color1", result);
}];

[[SensorsABTest sharedInstance] fastFetchABTestWithParamName:@"21" defaultValue:@(1111) completionHandler:^(id _Nullable result) {
NSLog(@"asyncFetchABTest,paramName:%@ - result:%@\n", @"21", result);
}];
}
break;

Expand Down Expand Up @@ -158,8 +148,8 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
case 3: { // Subject 多主体,fache 接口
switch (row) { //
case 0: { // user 主体
id result = [[SensorsABTest sharedInstance] fetchCacheABTestWithParamName:@"li" defaultValue:@(1111)];
NSLog(@"fetchCacheABTest,Subject User,paramName:%@ - result:%@\n", @"li", result);
id result = [[SensorsABTest sharedInstance] fetchCacheABTestWithParamName:@"cqs_index" defaultValue:@(1111)];
NSLog(@"fetchCacheABTest,Subject User,paramName:%@ - result:%@\n", @"cqs_index", result);
}
break;

Expand Down
2 changes: 1 addition & 1 deletion Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ target 'Example-iOS' do
use_frameworks!

# pod 'SensorsAnalyticsSDK'
# pod 'SensorsABTesting'
# pod 'SensorsABTesting'

pod 'SensorsABTesting', :path => './'
pod 'SensorsAnalyticsSDK', '>= 4.5.6'
Expand Down
51 changes: 38 additions & 13 deletions SensorsABTest/DataManger/SABExperimentDataManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@
/// 所有命中试验记录属性 key
static NSString * const kSABAllHitExperimentResultIdSourcesKey = @"abtest_result";

@interface SABExperimentDataManager()
@interface SABExperimentDataManager() {
__block SABFetchResultResponse *_resultResponse;
}

/// 试验结果
@property (atomic, strong) SABFetchResultResponse *resultResponse;
@property (nonatomic, strong) SABFetchResultResponse *resultResponse;

/// 试验参数白名单
///
Expand All @@ -66,11 +68,11 @@ @implementation SABExperimentDataManager
- (instancetype)initWithSerialQueue:(dispatch_queue_t)serialQueue {
self = [super init];
if (self) {
[self resgisterStorePlugins];

_serialQueue = serialQueue;
_hitRecordsManager = [[SABHitExperimentRecordsManager alloc] initWithSerialQueue:serialQueue];

[self resgisterStorePlugins];

[self buildUserIdenty];

// 解析事件触发配置
Expand Down Expand Up @@ -99,7 +101,7 @@ - (void)buildUserIdenty {
SABUserIdenty *userIdenty = [[SABUserIdenty alloc] initWithDistinctId:distinctId loginId:loginId anonymousId:anonymousId];

// 读取本地缓存前,需要先读取自定义主体 ID
NSDictionary *customIDs = [[SABStoreManager sharedInstance] dictionaryForKey:kSABCustomIDsFileName];
NSDictionary *customIDs = [SABStoreManager.sharedInstance dictionaryForKey:kSABCustomIDsFileName];
if (customIDs.count > 0) {
userIdenty.customIDs = customIDs;
}
Expand All @@ -109,7 +111,7 @@ - (void)buildUserIdenty {

- (void)updateCustomIDs:(NSDictionary<NSString *,NSString *> *)customIDs {
self.currentUserIndenty.customIDs = customIDs;
[[SABStoreManager sharedInstance] setObject:customIDs forKey:kSABCustomIDsFileName];
[SABStoreManager.sharedInstance setObject:customIDs forKey:kSABCustomIDsFileName];
}

- (void)updateUserIdenty {
Expand Down Expand Up @@ -159,6 +161,23 @@ - (void)asyncFetchAllExperimentWithRequest:(SABExperimentRequest *)requestData c
}];
}

#pragma mark - readWrite
// 增加读写锁,保证数据的线程安全
- (SABFetchResultResponse *)resultResponse {
__block SABFetchResultResponse *response;
sabtest_dispatch_safe_sync(self.serialQueue, ^{
response = _resultResponse;
});
return response;
}

- (void)setResultResponse:(SABFetchResultResponse *)resultResponse {
sabtest_dispatch_safe_async(self.serialQueue, ^{
_resultResponse = resultResponse;
});
}


#pragma mark - query
/// 查询扩展试验信息属性,作为预置属性采集
- (NSDictionary *)queryExtendedPropertiesWithExperimentResult:(SABExperimentResult *)resultData {
Expand All @@ -176,10 +195,15 @@ - (NSDictionary *)queryExtendedPropertiesWithExperimentResult:(SABExperimentResu
- (void)unarchiveExperimentResult {
dispatch_async(self.serialQueue, ^{

id result = [SABStoreManager.sharedInstance objectForKey:kSABExperimentResultFileName];
NSData *data = [SABStoreManager.sharedInstance objectForKey:kSABExperimentResultFileName];
if (![data isKindOfClass:NSData.class]) {
SABLogDebug(@"unarchiveExperimentResult objectForKey failure %@", data);
return;
}
SABFetchResultResponse *result = [NSKeyedUnarchiver unarchiveObjectWithData:data];
// 解析缓存
if (![result isKindOfClass:SABFetchResultResponse.class]) {
SABLogDebug(@"unarchiveExperimentResult failure %@", result);
SABLogDebug(@"unarchiveExperimentResult unarchiveObjectWithData failure %@", result);
return;
}

Expand All @@ -200,8 +224,9 @@ - (void)unarchiveExperimentResult {
/// 写入本地缓存
- (void)archiveExperimentResult:(SABFetchResultResponse *)resultResponse {
// 存储到本地
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:resultResponse];
dispatch_async(self.serialQueue, ^{
[SABStoreManager.sharedInstance setObject:resultResponse forKey:kSABExperimentResultFileName];
[SABStoreManager.sharedInstance setObject:data forKey:kSABExperimentResultFileName];
});
}

Expand All @@ -211,7 +236,7 @@ - (SABExperimentResult *)cachedExperimentResultWithParamName:(NSString *)paramNa
if (![SABValidUtils isValidString:paramName]) {
return nil;
}

__block SABExperimentResult *result = nil;
dispatch_sync(self.serialQueue, ^{
result = self.resultResponse.results[paramName];
Expand All @@ -224,7 +249,7 @@ - (SABExperimentResult *)queryOutResultWithParamName:(NSString *)paramName {
if (![SABValidUtils isValidString:paramName]) {
return nil;
}

__block SABExperimentResult *result = nil;
dispatch_sync(self.serialQueue, ^{
result = self.resultResponse.outResults[paramName];
Expand Down Expand Up @@ -324,11 +349,11 @@ - (BOOL)enableTrackWithHitExperiment:(SABExperimentResult *)resultData {
- (void)resgisterStorePlugins {
// 文件明文存储,兼容历史本地数据
SABFileStorePlugin *filePlugin = [[SABFileStorePlugin alloc] init];
[[SABStoreManager sharedInstance] registerStorePlugin:filePlugin];
[SABStoreManager.sharedInstance registerStorePlugin:filePlugin];

// 注册 SA 的自定义插件
for (id<SAStorePlugin> plugin in SABBridge.storePlugins) {
[[SABStoreManager sharedInstance] registerStorePlugin:plugin];
[SABStoreManager.sharedInstance registerStorePlugin:plugin];
}
}

Expand Down
1 change: 0 additions & 1 deletion SensorsABTest/DataManger/SABFetchResultResponse.m
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,6 @@ - (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.results forKey:@"results"];
[coder encodeObject:self.responseObject forKey:@"responseObject"];
[coder encodeObject:self.userIdenty forKey:@"userIdenty"];

[coder encodeObject:self.outResults forKey:@"outResults"];
[coder encodeObject:self.allResultIdOfResults forKey:@"allResultIdOfResults"];
}
Expand Down
9 changes: 7 additions & 2 deletions SensorsABTest/DataManger/SABHitExperimentRecordsManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ - (instancetype)initWithSerialQueue:(dispatch_queue_t)serialQueue {
/// 解析本地命中试验记录
- (void)unarchiveABTestHitExperimentRecordSources {
dispatch_async(self.serialQueue, ^{
NSArray <SABHitExperimentRecordSources *> *results = [SABStoreManager.sharedInstance objectForKey:kSABHitExperimentRecordSourcesFileName];
NSData *data = [SABStoreManager.sharedInstance objectForKey:kSABHitExperimentRecordSourcesFileName];
NSArray <SABHitExperimentRecordSources *> *results = nil;
if ([data isKindOfClass:NSData.class]) {
results = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
self.allHitExperimentRecordSources = [NSMutableArray arrayWithArray:results];
});
}
Expand All @@ -64,9 +68,10 @@ - (void)archiveABTestHitExperimentRecordSources {
if (self.allHitExperimentRecordSources.count == 0) {
return;
}
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:[self.allHitExperimentRecordSources copy]];
dispatch_async(self.serialQueue, ^{
// 存储到本地
[SABStoreManager.sharedInstance setObject:[self.allHitExperimentRecordSources copy] forKey:kSABHitExperimentRecordSourcesFileName];
[SABStoreManager.sharedInstance setObject:data forKey:kSABHitExperimentRecordSourcesFileName];
});
}

Expand Down
6 changes: 6 additions & 0 deletions SensorsABTest/SABConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,9 @@ extern NSNotificationName const kSABSAResetAnonymousIdNotification;

// 监听 SA 的生命周期通知,依赖版本 v2.6.3 及以上
extern NSNotificationName const kSABSAAppLifecycleStateDidChangeNotification;

#pragma mark 工具函数

void sabtest_dispatch_safe_sync(dispatch_queue_t queue,DISPATCH_NOESCAPE dispatch_block_t block);

void sabtest_dispatch_safe_async(dispatch_queue_t queue,DISPATCH_NOESCAPE dispatch_block_t block);
22 changes: 19 additions & 3 deletions SensorsABTest/SABConstants.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#import "SABConstants.h"

// 当前版本号
NSString *const kSABLibVersion = @"1.0.0";
NSString *const kSABLibVersion = @"1.0.1";

// SA 最低支持版本
NSString *const kSABMinSupportedSALibVersion = @"4.5.6";
Expand Down Expand Up @@ -62,11 +62,11 @@
NSTimeInterval const kSABFetchABTestResultDefaultTimeoutInterval = 30;

#pragma mark - fileName
NSString *const kSABExperimentResultFileName = @"SensorsABTestExperimentResultsResponse";
NSString *const kSABExperimentResultFileName = @"SensorsABTestExperimentResultsResponseData";

NSString *const kSABCustomIDsFileName = @"SensorsABTestCustomIDs";

NSString *const kSABHitExperimentRecordSourcesFileName = @"SensorsABTestHitExperimentRecordSources";
NSString *const kSABHitExperimentRecordSourcesFileName = @"SensorsABTestHitExperimentRecordSourcesData";

NSString *const kSABTestTrackConfigFileName = @"SensorsABTestTrackConfigSources";

Expand Down Expand Up @@ -95,3 +95,19 @@
// 监听 SA 的生命周期通知,依赖版本 v2.6.3 及以上
NSNotificationName const kSABSAAppLifecycleStateDidChangeNotification = @"com.sensorsdata.SAAppLifecycleStateDidChange";


void sabtest_dispatch_safe_async(dispatch_queue_t queue,DISPATCH_NOESCAPE dispatch_block_t block) {
if ((dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)) == dispatch_queue_get_label(queue)) {
block();
} else {
dispatch_async(queue, block);
}
}

void sabtest_dispatch_safe_sync(dispatch_queue_t queue,DISPATCH_NOESCAPE dispatch_block_t block) {
if ((dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)) == dispatch_queue_get_label(queue)) {
block();
} else {
dispatch_sync(queue, block);
}
}
2 changes: 0 additions & 2 deletions SensorsABTest/SABManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@
#import "SABPropertyValidator.h"
#import "SensorsABTestExperiment+Private.h"
#import "SABRequestManager.h"
#import "SABStoreManager.h"
#import "SABFileStorePlugin.h"
#import "SABNetwork.h"


Expand Down
3 changes: 2 additions & 1 deletion SensorsABTest/Store/SABFileStorePlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ - (nullable id)objectForKey:(nonnull NSString *)key {
}

- (void)setObject:(nullable id)value forKey:(nonnull NSString *)key {
if (!key) {
if (!key || !value) {
SABLogError(@"key should not be nil for file store");
return;
}
Expand All @@ -80,6 +80,7 @@ - (void)setObject:(nullable id)value forKey:(nonnull NSString *)key {
[[NSFileManager defaultManager] setAttributes:protection
ofItemAtPath:filePath
error:nil];

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:value];
if (![NSKeyedArchiver archiveRootObject:data toFile:filePath]) {
SABLogError(@"%@ unable to archive %@", self, key);
Expand Down
37 changes: 36 additions & 1 deletion SensorsABTest/Utils/SABJSONUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ @implementation SABJSONUtils

/// json 数据解析
+ (nullable id)JSONObjectWithData:(NSData *)data {
if (!data) {
if (![SABValidUtils isValidData:data]) {
SABLogInfo(@"json data is nil");
return nil;
}
Expand Down Expand Up @@ -85,4 +85,39 @@ + (NSString *)stringWithJSONObject:(id)obj {
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}

+ (id)JSONObjectByRemovingKeysWithNullValues:(id)object {
if (!object) {
return nil;
}
return [self JSONObjectByRemovingKeysWithNullValues:object options:0];
}

/// 移除 json 中的 null
/// 已有合法性判断,暂未使用
+ (id)JSONObjectByRemovingKeysWithNullValues:(id)object options:(NSJSONReadingOptions)readingOptions {
if ([object isKindOfClass:[NSArray class]]) {
NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:[(NSArray *)object count]];
for (id value in (NSArray *)object) {
if (![value isEqual:[NSNull null]]) {
[mutableArray addObject:[SABJSONUtils JSONObjectByRemovingKeysWithNullValues:value options:readingOptions]];
}
}

return (readingOptions & NSJSONReadingMutableContainers) ? mutableArray : [NSArray arrayWithArray:mutableArray];
} else if ([object isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:object];
for (id <NSCopying> key in [(NSDictionary *)object allKeys]) {
id value = (NSDictionary *)object[key];
if (!value || [value isEqual:[NSNull null]]) {
[mutableDictionary removeObjectForKey:key];
} else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) {
mutableDictionary[key] = [SABJSONUtils JSONObjectByRemovingKeysWithNullValues:value options:readingOptions];
}
}

return (readingOptions & NSJSONReadingMutableContainers) ? mutableDictionary : [NSDictionary dictionaryWithDictionary:mutableDictionary];
}

return object;
}
@end
2 changes: 2 additions & 0 deletions SensorsABTest/Utils/SABValidUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ NS_ASSUME_NONNULL_BEGIN
/// 是否为有效 Dictionary
+ (BOOL)isValidDictionary:(NSDictionary *)dictionary;

/// 是否为有效的 data
+ (BOOL)isValidData:(NSData *)data;
@end

NS_ASSUME_NONNULL_END
4 changes: 4 additions & 0 deletions SensorsABTest/Utils/SABValidUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@ + (BOOL)isValidDictionary:(NSDictionary *)dictionary {
return ([dictionary isKindOfClass:[NSDictionary class]] && ([dictionary count] > 0));
}

+ (BOOL)isValidData:(NSData *)data {
return ([data isKindOfClass:[NSData class]] && ([data length] > 0));
}

@end
4 changes: 2 additions & 2 deletions SensorsABTesting.podspec
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
Pod::Spec.new do |s|
s.name = 'SensorsABTesting'
s.version = "1.0.0"
s.version = "1.0.1"
s.summary = 'The official iOS/macOS SDK of Sensors A/B Testing.'
s.homepage = 'http://www.sensorsdata.cn'
s.license = { :type => 'Apache 2.0', :file => 'LICENSE' }
s.source = { :git => 'https://github.com/sensorsdata/abtesting-sdk-ios.git', :tag => 'v' + s.version.to_s}
s.author = 'Sensors Data'
s.ios.deployment_target = '9.0'
s.osx.deployment_target = '10.10'
s.osx.deployment_target = '10.13'
s.module_name = "SensorsABTest"
s.requires_arc = true
s.cocoapods_version = '>= 1.5.0'
Expand Down

0 comments on commit 092f667

Please sign in to comment.