Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 092f667

Browse files
author
王洋洋
committed
Release 1.0.1
1 parent 7cea80d commit 092f667

13 files changed

+119
-38
lines changed

Example/Example-iOS/ViewController.m

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
4848
case 0: { // INTEGER
4949
id result = [[SensorsABTest sharedInstance] fetchCacheABTestWithParamName:@"color1" defaultValue:@(1111)];
5050
NSLog(@"fetchCacheABTest,paramName:%@ - result:%@\n", @"color1", result);
51-
52-
// id result2 = [[SensorsABTest sharedInstance] fetchCacheABTestWithParamName:@"102" defaultValue:@(1111)];
53-
// NSLog(@"fetchCacheABTest,paramName:%@ - result:%@\n", @"102", result2);
5451
}
5552
break;
5653

@@ -83,10 +80,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
8380
[[SensorsABTest sharedInstance] asyncFetchABTestWithParamName:@"color1" defaultValue:@(1111) completionHandler:^(id _Nullable result) {
8481
NSLog(@"asyncFetchABTest,paramName:%@ - result:%@\n", @"color1", result);
8582
}];
86-
87-
[[SensorsABTest sharedInstance] asyncFetchABTestWithParamName:@"19" defaultValue:@(1111) completionHandler:^(id _Nullable result) {
88-
NSLog(@"asyncFetchABTest,paramName:%@ - result:%@\n", @"19", result);
89-
}];
9083
}
9184
break;
9285

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

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

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

Podfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ target 'Example-iOS' do
99
use_frameworks!
1010

1111
# pod 'SensorsAnalyticsSDK'
12-
# pod 'SensorsABTesting'
12+
# pod 'SensorsABTesting'
1313

1414
pod 'SensorsABTesting', :path => './'
1515
pod 'SensorsAnalyticsSDK', '>= 4.5.6'

SensorsABTest/DataManger/SABExperimentDataManager.m

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@
3838
/// 所有命中试验记录属性 key
3939
static NSString * const kSABAllHitExperimentResultIdSourcesKey = @"abtest_result";
4040

41-
@interface SABExperimentDataManager()
41+
@interface SABExperimentDataManager() {
42+
__block SABFetchResultResponse *_resultResponse;
43+
}
4244

4345
/// 试验结果
44-
@property (atomic, strong) SABFetchResultResponse *resultResponse;
46+
@property (nonatomic, strong) SABFetchResultResponse *resultResponse;
4547

4648
/// 试验参数白名单
4749
///
@@ -66,11 +68,11 @@ @implementation SABExperimentDataManager
6668
- (instancetype)initWithSerialQueue:(dispatch_queue_t)serialQueue {
6769
self = [super init];
6870
if (self) {
71+
[self resgisterStorePlugins];
72+
6973
_serialQueue = serialQueue;
7074
_hitRecordsManager = [[SABHitExperimentRecordsManager alloc] initWithSerialQueue:serialQueue];
7175

72-
[self resgisterStorePlugins];
73-
7476
[self buildUserIdenty];
7577

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

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

110112
- (void)updateCustomIDs:(NSDictionary<NSString *,NSString *> *)customIDs {
111113
self.currentUserIndenty.customIDs = customIDs;
112-
[[SABStoreManager sharedInstance] setObject:customIDs forKey:kSABCustomIDsFileName];
114+
[SABStoreManager.sharedInstance setObject:customIDs forKey:kSABCustomIDsFileName];
113115
}
114116

115117
- (void)updateUserIdenty {
@@ -159,6 +161,23 @@ - (void)asyncFetchAllExperimentWithRequest:(SABExperimentRequest *)requestData c
159161
}];
160162
}
161163

164+
#pragma mark - readWrite
165+
// 增加读写锁,保证数据的线程安全
166+
- (SABFetchResultResponse *)resultResponse {
167+
__block SABFetchResultResponse *response;
168+
sabtest_dispatch_safe_sync(self.serialQueue, ^{
169+
response = _resultResponse;
170+
});
171+
return response;
172+
}
173+
174+
- (void)setResultResponse:(SABFetchResultResponse *)resultResponse {
175+
sabtest_dispatch_safe_async(self.serialQueue, ^{
176+
_resultResponse = resultResponse;
177+
});
178+
}
179+
180+
162181
#pragma mark - query
163182
/// 查询扩展试验信息属性,作为预置属性采集
164183
- (NSDictionary *)queryExtendedPropertiesWithExperimentResult:(SABExperimentResult *)resultData {
@@ -176,10 +195,15 @@ - (NSDictionary *)queryExtendedPropertiesWithExperimentResult:(SABExperimentResu
176195
- (void)unarchiveExperimentResult {
177196
dispatch_async(self.serialQueue, ^{
178197

179-
id result = [SABStoreManager.sharedInstance objectForKey:kSABExperimentResultFileName];
198+
NSData *data = [SABStoreManager.sharedInstance objectForKey:kSABExperimentResultFileName];
199+
if (![data isKindOfClass:NSData.class]) {
200+
SABLogDebug(@"unarchiveExperimentResult objectForKey failure %@", data);
201+
return;
202+
}
203+
SABFetchResultResponse *result = [NSKeyedUnarchiver unarchiveObjectWithData:data];
180204
// 解析缓存
181205
if (![result isKindOfClass:SABFetchResultResponse.class]) {
182-
SABLogDebug(@"unarchiveExperimentResult failure %@", result);
206+
SABLogDebug(@"unarchiveExperimentResult unarchiveObjectWithData failure %@", result);
183207
return;
184208
}
185209

@@ -200,8 +224,9 @@ - (void)unarchiveExperimentResult {
200224
/// 写入本地缓存
201225
- (void)archiveExperimentResult:(SABFetchResultResponse *)resultResponse {
202226
// 存储到本地
227+
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:resultResponse];
203228
dispatch_async(self.serialQueue, ^{
204-
[SABStoreManager.sharedInstance setObject:resultResponse forKey:kSABExperimentResultFileName];
229+
[SABStoreManager.sharedInstance setObject:data forKey:kSABExperimentResultFileName];
205230
});
206231
}
207232

@@ -211,7 +236,7 @@ - (SABExperimentResult *)cachedExperimentResultWithParamName:(NSString *)paramNa
211236
if (![SABValidUtils isValidString:paramName]) {
212237
return nil;
213238
}
214-
239+
215240
__block SABExperimentResult *result = nil;
216241
dispatch_sync(self.serialQueue, ^{
217242
result = self.resultResponse.results[paramName];
@@ -224,7 +249,7 @@ - (SABExperimentResult *)queryOutResultWithParamName:(NSString *)paramName {
224249
if (![SABValidUtils isValidString:paramName]) {
225250
return nil;
226251
}
227-
252+
228253
__block SABExperimentResult *result = nil;
229254
dispatch_sync(self.serialQueue, ^{
230255
result = self.resultResponse.outResults[paramName];
@@ -324,11 +349,11 @@ - (BOOL)enableTrackWithHitExperiment:(SABExperimentResult *)resultData {
324349
- (void)resgisterStorePlugins {
325350
// 文件明文存储,兼容历史本地数据
326351
SABFileStorePlugin *filePlugin = [[SABFileStorePlugin alloc] init];
327-
[[SABStoreManager sharedInstance] registerStorePlugin:filePlugin];
352+
[SABStoreManager.sharedInstance registerStorePlugin:filePlugin];
328353

329354
// 注册 SA 的自定义插件
330355
for (id<SAStorePlugin> plugin in SABBridge.storePlugins) {
331-
[[SABStoreManager sharedInstance] registerStorePlugin:plugin];
356+
[SABStoreManager.sharedInstance registerStorePlugin:plugin];
332357
}
333358
}
334359

SensorsABTest/DataManger/SABFetchResultResponse.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,6 @@ - (void)encodeWithCoder:(NSCoder *)coder {
600600
[coder encodeObject:self.results forKey:@"results"];
601601
[coder encodeObject:self.responseObject forKey:@"responseObject"];
602602
[coder encodeObject:self.userIdenty forKey:@"userIdenty"];
603-
604603
[coder encodeObject:self.outResults forKey:@"outResults"];
605604
[coder encodeObject:self.allResultIdOfResults forKey:@"allResultIdOfResults"];
606605
}

SensorsABTest/DataManger/SABHitExperimentRecordsManager.m

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ - (instancetype)initWithSerialQueue:(dispatch_queue_t)serialQueue {
5454
/// 解析本地命中试验记录
5555
- (void)unarchiveABTestHitExperimentRecordSources {
5656
dispatch_async(self.serialQueue, ^{
57-
NSArray <SABHitExperimentRecordSources *> *results = [SABStoreManager.sharedInstance objectForKey:kSABHitExperimentRecordSourcesFileName];
57+
NSData *data = [SABStoreManager.sharedInstance objectForKey:kSABHitExperimentRecordSourcesFileName];
58+
NSArray <SABHitExperimentRecordSources *> *results = nil;
59+
if ([data isKindOfClass:NSData.class]) {
60+
results = [NSKeyedUnarchiver unarchiveObjectWithData:data];
61+
}
5862
self.allHitExperimentRecordSources = [NSMutableArray arrayWithArray:results];
5963
});
6064
}
@@ -64,9 +68,10 @@ - (void)archiveABTestHitExperimentRecordSources {
6468
if (self.allHitExperimentRecordSources.count == 0) {
6569
return;
6670
}
71+
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:[self.allHitExperimentRecordSources copy]];
6772
dispatch_async(self.serialQueue, ^{
6873
// 存储到本地
69-
[SABStoreManager.sharedInstance setObject:[self.allHitExperimentRecordSources copy] forKey:kSABHitExperimentRecordSourcesFileName];
74+
[SABStoreManager.sharedInstance setObject:data forKey:kSABHitExperimentRecordSourcesFileName];
7075
});
7176
}
7277

SensorsABTest/SABConstants.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,9 @@ extern NSNotificationName const kSABSAResetAnonymousIdNotification;
9393

9494
// 监听 SA 的生命周期通知,依赖版本 v2.6.3 及以上
9595
extern NSNotificationName const kSABSAAppLifecycleStateDidChangeNotification;
96+
97+
#pragma mark 工具函数
98+
99+
void sabtest_dispatch_safe_sync(dispatch_queue_t queue,DISPATCH_NOESCAPE dispatch_block_t block);
100+
101+
void sabtest_dispatch_safe_async(dispatch_queue_t queue,DISPATCH_NOESCAPE dispatch_block_t block);

SensorsABTest/SABConstants.m

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#import "SABConstants.h"
2626

2727
// 当前版本号
28-
NSString *const kSABLibVersion = @"1.0.0";
28+
NSString *const kSABLibVersion = @"1.0.1";
2929

3030
// SA 最低支持版本
3131
NSString *const kSABMinSupportedSALibVersion = @"4.5.6";
@@ -62,11 +62,11 @@
6262
NSTimeInterval const kSABFetchABTestResultDefaultTimeoutInterval = 30;
6363

6464
#pragma mark - fileName
65-
NSString *const kSABExperimentResultFileName = @"SensorsABTestExperimentResultsResponse";
65+
NSString *const kSABExperimentResultFileName = @"SensorsABTestExperimentResultsResponseData";
6666

6767
NSString *const kSABCustomIDsFileName = @"SensorsABTestCustomIDs";
6868

69-
NSString *const kSABHitExperimentRecordSourcesFileName = @"SensorsABTestHitExperimentRecordSources";
69+
NSString *const kSABHitExperimentRecordSourcesFileName = @"SensorsABTestHitExperimentRecordSourcesData";
7070

7171
NSString *const kSABTestTrackConfigFileName = @"SensorsABTestTrackConfigSources";
7272

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

98+
99+
void sabtest_dispatch_safe_async(dispatch_queue_t queue,DISPATCH_NOESCAPE dispatch_block_t block) {
100+
if ((dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)) == dispatch_queue_get_label(queue)) {
101+
block();
102+
} else {
103+
dispatch_async(queue, block);
104+
}
105+
}
106+
107+
void sabtest_dispatch_safe_sync(dispatch_queue_t queue,DISPATCH_NOESCAPE dispatch_block_t block) {
108+
if ((dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)) == dispatch_queue_get_label(queue)) {
109+
block();
110+
} else {
111+
dispatch_sync(queue, block);
112+
}
113+
}

SensorsABTest/SABManager.m

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737
#import "SABPropertyValidator.h"
3838
#import "SensorsABTestExperiment+Private.h"
3939
#import "SABRequestManager.h"
40-
#import "SABStoreManager.h"
41-
#import "SABFileStorePlugin.h"
4240
#import "SABNetwork.h"
4341

4442

SensorsABTest/Store/SABFileStorePlugin.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ - (nullable id)objectForKey:(nonnull NSString *)key {
6262
}
6363

6464
- (void)setObject:(nullable id)value forKey:(nonnull NSString *)key {
65-
if (!key) {
65+
if (!key || !value) {
6666
SABLogError(@"key should not be nil for file store");
6767
return;
6868
}
@@ -80,6 +80,7 @@ - (void)setObject:(nullable id)value forKey:(nonnull NSString *)key {
8080
[[NSFileManager defaultManager] setAttributes:protection
8181
ofItemAtPath:filePath
8282
error:nil];
83+
8384
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:value];
8485
if (![NSKeyedArchiver archiveRootObject:data toFile:filePath]) {
8586
SABLogError(@"%@ unable to archive %@", self, key);

SensorsABTest/Utils/SABJSONUtils.m

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ @implementation SABJSONUtils
3030

3131
/// json 数据解析
3232
+ (nullable id)JSONObjectWithData:(NSData *)data {
33-
if (!data) {
33+
if (![SABValidUtils isValidData:data]) {
3434
SABLogInfo(@"json data is nil");
3535
return nil;
3636
}
@@ -85,4 +85,39 @@ + (NSString *)stringWithJSONObject:(id)obj {
8585
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
8686
}
8787

88+
+ (id)JSONObjectByRemovingKeysWithNullValues:(id)object {
89+
if (!object) {
90+
return nil;
91+
}
92+
return [self JSONObjectByRemovingKeysWithNullValues:object options:0];
93+
}
94+
95+
/// 移除 json 中的 null
96+
/// 已有合法性判断,暂未使用
97+
+ (id)JSONObjectByRemovingKeysWithNullValues:(id)object options:(NSJSONReadingOptions)readingOptions {
98+
if ([object isKindOfClass:[NSArray class]]) {
99+
NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:[(NSArray *)object count]];
100+
for (id value in (NSArray *)object) {
101+
if (![value isEqual:[NSNull null]]) {
102+
[mutableArray addObject:[SABJSONUtils JSONObjectByRemovingKeysWithNullValues:value options:readingOptions]];
103+
}
104+
}
105+
106+
return (readingOptions & NSJSONReadingMutableContainers) ? mutableArray : [NSArray arrayWithArray:mutableArray];
107+
} else if ([object isKindOfClass:[NSDictionary class]]) {
108+
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:object];
109+
for (id <NSCopying> key in [(NSDictionary *)object allKeys]) {
110+
id value = (NSDictionary *)object[key];
111+
if (!value || [value isEqual:[NSNull null]]) {
112+
[mutableDictionary removeObjectForKey:key];
113+
} else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) {
114+
mutableDictionary[key] = [SABJSONUtils JSONObjectByRemovingKeysWithNullValues:value options:readingOptions];
115+
}
116+
}
117+
118+
return (readingOptions & NSJSONReadingMutableContainers) ? mutableDictionary : [NSDictionary dictionaryWithDictionary:mutableDictionary];
119+
}
120+
121+
return object;
122+
}
88123
@end

0 commit comments

Comments
 (0)