Commit 2d57d66e authored by 井庆林's avatar 井庆林

优化

parent 19039216
...@@ -66,15 +66,19 @@ NSString *const MockCityId = @"beijing"; ...@@ -66,15 +66,19 @@ NSString *const MockCityId = @"beijing";
// [Phobos track:@"page_view" attributes:dict]; // [Phobos track:@"page_view" attributes:dict];
// array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey]; // array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
for (int i = 0; i < 200; i++) { // for (int i = 0; i < 200; i++) {
[Phobos track:[NSString stringWithFormat:@"tt-%d", i] attributes:dict sendNow:YES]; // [Phobos track:[NSString stringWithFormat:@"phobos>>>tt-%d", i] attributes:dict sendNow:YES];
[Phobos track:[NSString stringWithFormat:@"pv-%d", i] attributes:dict sendNow:(arc4random() % 2 == 0)]; // [Phobos track:[NSString stringWithFormat:@"phobos>>>pv-%d", i] attributes:dict sendNow:(arc4random() % 2 == 0)];
} // NSUInteger count = [Phobos fetchToBeSendPhobosDataCount];
for (int i = 5; i < 5; i++) { // NSLog(@"%lu", (unsigned long)count);
dispatch_async(dispatch_get_global_queue(0, 0), ^{ // }
[Phobos track:[NSString stringWithFormat:@"ay-%d", i] attributes:dict sendNow:YES]; // for (int i = 0; i < 200; i++) {
}); // dispatch_async(dispatch_get_global_queue(0, 0), ^{
} // NSUInteger count = [Phobos fetchToBeSendPhobosDataCount];
// NSLog(@"%lu", (unsigned long)count);
// [Phobos track:[NSString stringWithFormat:@"phobos>>>ay-%d", i] attributes:dict sendNow:YES];
// });
// }
} }
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
......
...@@ -32,8 +32,6 @@ static NewPhobos *_sharedClient; ...@@ -32,8 +32,6 @@ static NewPhobos *_sharedClient;
@implementation NewPhobos @implementation NewPhobos
static dispatch_semaphore_t _phobos_semaphore;
+ (NewPhobos *)clientWithAppName:(NSString *)appName channelId:(NSString *)channelId{ + (NewPhobos *)clientWithAppName:(NSString *)appName channelId:(NSString *)channelId{
NewPhobos.sharedClient.appName = appName; NewPhobos.sharedClient.appName = appName;
NewPhobos.sharedClient.channelId = channelId; NewPhobos.sharedClient.channelId = channelId;
...@@ -42,7 +40,6 @@ static dispatch_semaphore_t _phobos_semaphore; ...@@ -42,7 +40,6 @@ static dispatch_semaphore_t _phobos_semaphore;
- (instancetype)init { - (instancetype)init {
if (self = [super init]) { if (self = [super init]) {
_phobos_semaphore = dispatch_semaphore_create(1);
_appName = @""; _appName = @"";
_channelId = @""; _channelId = @"";
_logEnabled = NO; _logEnabled = NO;
...@@ -218,7 +215,7 @@ static dispatch_semaphore_t _phobos_semaphore; ...@@ -218,7 +215,7 @@ static dispatch_semaphore_t _phobos_semaphore;
@"uuid": [PhobosUtil deviceId], @"uuid": [PhobosUtil deviceId],
@"build_version_release": [[UIDevice currentDevice] systemVersion], @"build_version_release": [[UIDevice currentDevice] systemVersion],
}; };
[NewPhobos track:@"on_app_session_over" attributes:dict]; [NewPhobos trackSessionOverWithAttributes:dict];
[GMCache removeObjectAtDocumentPathWithkey:PhobosBeginTime]; [GMCache removeObjectAtDocumentPathWithkey:PhobosBeginTime];
//当前session结束之后,把id置为0 //当前session结束之后,把id置为0
_serialId = 0; _serialId = 0;
...@@ -328,7 +325,6 @@ static dispatch_semaphore_t _phobos_semaphore; ...@@ -328,7 +325,6 @@ static dispatch_semaphore_t _phobos_semaphore;
[deviceParams setValue:[PhobosUtil getIPAddress:YES] forKey:@"ip"]; [deviceParams setValue:[PhobosUtil getIPAddress:YES] forKey:@"ip"];
[deviceParams setValue:PhobosSafeString(_networkStatus) forKey:@"net_type"]; [deviceParams setValue:PhobosSafeString(_networkStatus) forKey:@"net_type"];
[deviceParams setValue:PhobosSafeString([PhobosUtil platform]) forKey:@"model"]; [deviceParams setValue:PhobosSafeString([PhobosUtil platform]) forKey:@"model"];
[deviceParams setValue:@(_isGray) forKey:@"isGray"];
[deviceParams setValue:PhobosSafeString([UIDevice currentDevice].systemVersion) forKey:@"sys_version"]; [deviceParams setValue:PhobosSafeString([UIDevice currentDevice].systemVersion) forKey:@"sys_version"];
NSMutableDictionary *appParams = [NSMutableDictionary new]; NSMutableDictionary *appParams = [NSMutableDictionary new];
...@@ -337,6 +333,7 @@ static dispatch_semaphore_t _phobos_semaphore; ...@@ -337,6 +333,7 @@ static dispatch_semaphore_t _phobos_semaphore;
[appParams setValue:PhobosSafeString(_appVersion) forKey:@"version"]; [appParams setValue:PhobosSafeString(_appVersion) forKey:@"version"];
[appParams setValue:PhobosSafeString(_channelId) forKey:@"channel"]; [appParams setValue:PhobosSafeString(_channelId) forKey:@"channel"];
[appParams setValue:PhobosSafeString(_userType) forKey:@"user_type"]; [appParams setValue:PhobosSafeString(_userType) forKey:@"user_type"];
[appParams setValue:@(_isGray) forKey:@"is_gray"];
[appParams setValue:PhobosSafeString(_currentCityId) forKey:@"current_city_id"]; [appParams setValue:PhobosSafeString(_currentCityId) forKey:@"current_city_id"];
[appParams setValue:@(_serialId++) forKey:@"serial_id"]; [appParams setValue:@(_serialId++) forKey:@"serial_id"];
...@@ -381,11 +378,11 @@ static dispatch_semaphore_t _phobos_semaphore; ...@@ -381,11 +378,11 @@ static dispatch_semaphore_t _phobos_semaphore;
} }
+ (void)onClickButtonWithAttributes:(NSDictionary *)attributes { + (void)onClickButtonWithAttributes:(NSDictionary *)attributes {
[self track:@"on_cick_button" attributes:attributes]; [self track:@"on_click_button" attributes:attributes];
} }
+ (void)onClickButtonWithAttributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow { + (void)onClickButtonWithAttributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow {
[self track:@"on_cick_button" attributes:attributes sendNow:sendNow]; [self track:@"on_click_button" attributes:attributes sendNow:sendNow];
} }
+ (void)track:(NSString *)eventName{ + (void)track:(NSString *)eventName{
...@@ -412,25 +409,34 @@ static dispatch_semaphore_t _phobos_semaphore; ...@@ -412,25 +409,34 @@ static dispatch_semaphore_t _phobos_semaphore;
NSDictionary *dataDict = [_sharedClient prepareDictionaryForEvent:eventName attributes:attributes]; NSDictionary *dataDict = [_sharedClient prepareDictionaryForEvent:eventName attributes:attributes];
@try { @try {
NSData *JSON = [PhobosUtil encodeJSON:dataDict]; NSData *JSON = [PhobosUtil encodeJSON:dataDict];
[PhobosDataManager insertData:dataDict sendAPI:currentAPI]; [PhobosDataManager insertData:dataDict sendAPI:currentAPI completion:^(BOOL contextDidSave, NSError * _Nullable error) {
[self disposeSendDataWithImmediately:sendNow]; [self disposeSendDataWithImmediately:sendNow];
}];
} @catch (NSException *exception) { } @catch (NSException *exception) {
NSAssert(NO, @"哎呀呀,VALUE不能为NSObject "); NSAssert(NO, @"哎呀呀,VALUE不能为NSObject ");
} }
} }
/**
* 为app_session_over提供埋点发送
* 其他情况在写入数据库成功,异步回调后在发送数据
* 这样可以优化发送次数,并能保障数据安全,但因为completion是使用主线程回调的,但进入后台后,主线程会休眠,所以单独处理该埋点
*/
+ (void)trackSessionOverWithAttributes:(NSDictionary *)attributes {
NSDictionary *dataDict = [_sharedClient prepareDictionaryForEvent:@"on_app_session_over" attributes:attributes];
[PhobosDataManager insertData:dataDict sendAPI:_sharedClient.serverAPI completion:nil];
[self disposeSendDataWithImmediately:YES];
}
/** /**
* 处理发送数据 * 处理发送数据
*/ */
+ (void)disposeSendDataWithImmediately:(BOOL)immediately { + (void)disposeSendDataWithImmediately:(BOOL)immediately {
NSInteger count = [PhobosDataManager fetchCountOfToBeSendEntities]; NSInteger count = [PhobosDataManager fetchCountOfToBeSendEntities];
if (immediately || count >= PhobosShardCount) { if (immediately || count >= PhobosShardCount) {
dispatch_semaphore_wait(_phobos_semaphore, DISPATCH_TIME_FOREVER); NSArray<PhobosSendDataEntity *> *entities = [PhobosDataManager fetchToBeSendDataEntitiesAndUpdateWithSendStatus:PhobosDataSendStatusSending];
NSArray<PhobosSendDataEntity *> *entities = [PhobosDataManager fetchToBeSendDataEntities];
[PhobosDataManager updateDataEntities:entities sendStatus:PhobosDataSendStatusSending];
dispatch_semaphore_signal(_phobos_semaphore);
[PhobosSendManager sendDataWithEntities:entities completion:^(NSArray<PhobosSendDataEntity *> * _Nonnull finishEntities, NSInteger code) { [PhobosSendManager sendDataWithEntities:entities completion:^(NSArray<PhobosSendDataEntity *> * _Nonnull finishEntities, NSInteger code) {
[PhobosDataManager updateDataEntities:finishEntities sendStatus:(code == 200 ? PhobosDataSendStatusFinish : PhobosDataSendStatusError)]; [PhobosDataManager updateDataEntities:finishEntities sendStatus:(code == 200 ? PhobosDataSendStatusFinish : PhobosDataSendStatusError) completion:nil];
}]; }];
} }
} }
......
...@@ -65,7 +65,7 @@ static BOOL isGray = NO; ...@@ -65,7 +65,7 @@ static BOOL isGray = NO;
if (isGray) { if (isGray) {
[NewPhobos onClickButtonWithAttributes:attributes]; [NewPhobos onClickButtonWithAttributes:attributes];
} else { } else {
[self track:@"on_cick_button" attributes:attributes]; [self track:@"on_click_button" attributes:attributes];
} }
} }
...@@ -73,7 +73,7 @@ static BOOL isGray = NO; ...@@ -73,7 +73,7 @@ static BOOL isGray = NO;
if (isGray) { if (isGray) {
[NewPhobos onClickButtonWithAttributes:attributes sendNow:sendNow]; [NewPhobos onClickButtonWithAttributes:attributes sendNow:sendNow];
} else { } else {
[self track:@"on_cick_button" attributes:attributes sendNow:sendNow]; [self track:@"on_click_button" attributes:attributes sendNow:sendNow];
} }
} }
......
...@@ -20,23 +20,22 @@ typedef NS_ENUM(NSInteger, PhobosDataSendStatus) { ...@@ -20,23 +20,22 @@ typedef NS_ENUM(NSInteger, PhobosDataSendStatus) {
@interface PhobosDataManager : NSObject @interface PhobosDataManager : NSObject
/** 获取待发送数据,包含待发送数据和发送失败数据 */
+ (NSArray<PhobosSendDataEntity *> *)fetchToBeSendDataEntities;
/** /**
* 通过 searchFilter 获取数据 * 获取待发送和发送失败的数据数量
*/ */
+ (NSArray<PhobosSendDataEntity *> *)fetchDataEntitiesWithPredicate:(NSPredicate *)searchFilter; + (NSUInteger)fetchCountOfToBeSendEntities;
/** /**
* 获取待发送和发送失败的数据数量 * 获取待发送数据,包含待发送数据和发送失败数据
* predicate 通过谓词获取相应的数据
*/ */
+ (NSUInteger)fetchCountOfToBeSendEntities; + (NSArray<PhobosSendDataEntity *> *)fetchToBeSendDataEntities;
+ (NSArray<PhobosSendDataEntity *> *)fetchDataEntitiesWithPredicate:(NSPredicate *)predicate;
/** /**
* 通过 searchFilter 获取数据数量 * 获取待发送数据,包含待发送数据和发送失败数据, 并修改状态为sendStatus
*/ */
+ (NSUInteger)fetchCountOfEntitiesWithPredicate:(NSPredicate *)searchFilter; + (NSArray<PhobosSendDataEntity *> *)fetchToBeSendDataEntitiesAndUpdateWithSendStatus:(PhobosDataSendStatus)sendStatus;
/** /**
* 插入埋点数据 * 插入埋点数据
...@@ -45,7 +44,6 @@ typedef NS_ENUM(NSInteger, PhobosDataSendStatus) { ...@@ -45,7 +44,6 @@ typedef NS_ENUM(NSInteger, PhobosDataSendStatus) {
* completion 插入数据库成功后的回调方法,在保存完成后调用的完成块。如果发生错误,块将以“BOOL”和“NSError”实例的形式传递成功状态。总是在主队列上调用。 * completion 插入数据库成功后的回调方法,在保存完成后调用的完成块。如果发生错误,块将以“BOOL”和“NSError”实例的形式传递成功状态。总是在主队列上调用。
* 该方法调用完成,fetch方法获取相应的数据就可获取到,不需要等completion回调。 * 该方法调用完成,fetch方法获取相应的数据就可获取到,不需要等completion回调。
*/ */
+ (void)insertData:(NSDictionary *)data sendAPI:(NSString *)sendAPI;
+ (void)insertData:(NSDictionary *)data sendAPI:(NSString *)sendAPI completion:(MRSaveCompletionHandler)completion; + (void)insertData:(NSDictionary *)data sendAPI:(NSString *)sendAPI completion:(MRSaveCompletionHandler)completion;
/** /**
...@@ -55,13 +53,12 @@ typedef NS_ENUM(NSInteger, PhobosDataSendStatus) { ...@@ -55,13 +53,12 @@ typedef NS_ENUM(NSInteger, PhobosDataSendStatus) {
* completion 插入数据库成功后的回调方法,在保存完成后调用的完成块。如果发生错误,块将以“BOOL”和“NSError”实例的形式传递成功状态。总是在主队列上调用。 * completion 插入数据库成功后的回调方法,在保存完成后调用的完成块。如果发生错误,块将以“BOOL”和“NSError”实例的形式传递成功状态。总是在主队列上调用。
* 该方法调用完成,fetch方法获取相应的数据就可获取到,不需要等completion回调。 * 该方法调用完成,fetch方法获取相应的数据就可获取到,不需要等completion回调。
*/ */
+ (void)updateDataEntities:(NSArray<PhobosSendDataEntity *> *)entities sendStatus:(PhobosDataSendStatus)sendStatus;
+ (void)updateDataEntities:(NSArray<PhobosSendDataEntity *> *)entities sendStatus:(PhobosDataSendStatus)sendStatus completion:(MRSaveCompletionHandler)completion; + (void)updateDataEntities:(NSArray<PhobosSendDataEntity *> *)entities sendStatus:(PhobosDataSendStatus)sendStatus completion:(MRSaveCompletionHandler)completion;
/** /**
* 删除数据 * 删除所有数据
* 仅限单元测试使用
*/ */
+ (void)deleteDataEntities:(NSArray<PhobosSendDataEntity *> *)entities;
+ (void)deleteAllEntities; + (void)deleteAllEntities;
@end @end
......
...@@ -15,118 +15,163 @@ ...@@ -15,118 +15,163 @@
@implementation PhobosDataManager @implementation PhobosDataManager
static NSManagedObjectContext *PhobosDefaultContext; static NSManagedObjectContext *PhobosDefaultContext;
static dispatch_semaphore_t phobos_semaphore_t; static NSUInteger PhobosToBeSendEntitiesCount = 0;
+ (void)initialize { + (void)initialize {
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
phobos_semaphore_t = dispatch_semaphore_create(1); [self setupSDK];
[self resetData];
// 创建 NSManagedObjectContext,供埋点库访问CoreData库使用
PhobosDefaultContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
// 获取埋点数据的实体
NSURL *modelURL = [bundle URLForResource:@"GMPhobosData" withExtension:@"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
// 创建持久化存储调度器
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
// 创建并关联SQLite数据库文件,如果已经存在则不会重复创建
NSString *dataPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
dataPath = [dataPath stringByAppendingFormat:@"/%@.sqlite",@"GMPhobos"];
[coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:dataPath] options:nil error:nil];
// 设置storeCoordinator
PhobosDefaultContext.persistentStoreCoordinator = coordinator;
/** 将上次没有获取到发送结果的数据的状态修改为发送失败,待下次重新发送 */
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = %d", PhobosDataSendStatusSending];
NSArray<PhobosSendDataEntity *> *entities = [self fetchDataEntitiesWithPredicate:predicate];
[self updateDataEntities:entities sendStatus:PhobosDataSendStatusError];
/** 将发送成功的数据删除 */
NSPredicate *finishPredicate = [NSPredicate predicateWithFormat:@"status = %d", PhobosDataSendStatusFinish];
NSArray<PhobosSendDataEntity *> *finishEntities = [self fetchDataEntitiesWithPredicate:finishPredicate];
[self deleteDataEntities:finishEntities];
}); });
} }
+ (NSArray<PhobosSendDataEntity *> *)fetchToBeSendDataEntities { + (NSUInteger)fetchCountOfToBeSendEntities {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = %d or status = %d", PhobosDataSendStatusToBeSend, PhobosDataSendStatusError]; return PhobosToBeSendEntitiesCount;
return [self fetchDataEntitiesWithPredicate:predicate];
}
+ (NSArray<PhobosSendDataEntity *> *)fetchDataEntitiesWithPredicate:(NSPredicate *)searchFilter {
return [PhobosSendDataEntity MR_findAllWithPredicate:searchFilter inContext:PhobosDefaultContext];
} }
+ (NSUInteger)fetchCountOfToBeSendEntities { + (NSArray<PhobosSendDataEntity *> *)fetchToBeSendDataEntities {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = %d or status = %d", PhobosDataSendStatusToBeSend, PhobosDataSendStatusError]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = %d or status = %d", PhobosDataSendStatusToBeSend, PhobosDataSendStatusError];
return [self fetchCountOfEntitiesWithPredicate:predicate]; return [self fetchDataEntitiesWithPredicate:predicate];
} }
+ (NSUInteger)fetchCountOfEntitiesWithPredicate:(NSPredicate *)searchFilter { + (NSArray<PhobosSendDataEntity *> *)fetchDataEntitiesWithPredicate:(NSPredicate *)predicate {
return [[PhobosSendDataEntity MR_numberOfEntitiesWithPredicate:searchFilter inContext:PhobosDefaultContext] integerValue]; __block NSArray *results = nil;
[[self PhobosContext] performBlockAndWait:^{
results = [self noWaitFetchDataEntitiesWithPredicate:predicate];
}];
return results;
} }
+ (void)insertData:(NSDictionary *)data sendAPI:(NSString *)sendAPI { + (NSArray<PhobosSendDataEntity *> *)fetchToBeSendDataEntitiesAndUpdateWithSendStatus:(PhobosDataSendStatus)sendStatus {
[self insertData:data sendAPI:sendAPI completion:nil]; __block NSArray *results = nil;
[[self PhobosContext] performBlockAndWait:^{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = %d or status = %d", PhobosDataSendStatusToBeSend, PhobosDataSendStatusError];
results = [self noWaitFetchDataEntitiesWithPredicate:predicate];
[self noWaitUpdateEntities:results sendStatus:sendStatus completion:nil];
}];
return results;
} }
+ (void)insertData:(NSDictionary *)data sendAPI:(NSString *)sendAPI completion:(MRSaveCompletionHandler)completion { + (void)insertData:(NSDictionary *)data sendAPI:(NSString *)sendAPI completion:(MRSaveCompletionHandler)completion {
if (!sendAPI || [sendAPI isEqualToString:@""] || !data) { if (!sendAPI || [sendAPI isEqualToString:@""] || !data) {
return; return;
} }
dispatch_semaphore_wait(phobos_semaphore_t, DISPATCH_TIME_FOREVER); [[self PhobosContext] performBlockAndWait:^{
PhobosSendDataEntity *entity = [PhobosSendDataEntity MR_createEntityInContext:PhobosDefaultContext]; PhobosSendDataEntity *entity = [PhobosSendDataEntity MR_createEntityInContext:[self PhobosContext]];
entity.data = [data mj_JSONData]; entity.data = [data mj_JSONData];
entity.api = sendAPI; entity.api = sendAPI;
entity.status = PhobosDataSendStatusToBeSend; entity.status = PhobosDataSendStatusToBeSend;
entity.id = mach_absolute_time(); entity.id = mach_absolute_time();
dispatch_semaphore_signal(phobos_semaphore_t); PhobosToBeSendEntitiesCount++;
[self saveWithCompletion:completion]; [self saveWithCompletion:completion];
} }];
+ (void)updateDataEntities:(NSArray<PhobosSendDataEntity *> *)entities sendStatus:(PhobosDataSendStatus)sendStatus {
[self updateDataEntities:entities sendStatus:sendStatus completion:nil];
} }
+ (void)updateDataEntities:(NSArray<PhobosSendDataEntity *> *)entities sendStatus:(PhobosDataSendStatus)sendStatus completion:(MRSaveCompletionHandler)completion { + (void)updateDataEntities:(NSArray<PhobosSendDataEntity *> *)entities sendStatus:(PhobosDataSendStatus)sendStatus completion:(MRSaveCompletionHandler)completion {
if (entities.count > 0) { if (entities.count > 0) {
dispatch_semaphore_wait(phobos_semaphore_t, DISPATCH_TIME_FOREVER); [[self PhobosContext] performBlockAndWait :^{
[entities enumerateObjectsUsingBlock:^(PhobosSendDataEntity *obj, NSUInteger idx, BOOL * _Nonnull stop) { [self noWaitUpdateEntities:entities sendStatus:sendStatus completion:completion];
obj.status = sendStatus;
}]; }];
dispatch_semaphore_signal(phobos_semaphore_t);
[self saveWithCompletion:completion];
} }
} }
+ (void)deleteDataEntities:(NSArray<PhobosSendDataEntity *> *)entities { + (void)deleteAllEntities {
if (entities.count > 0) { [[self PhobosContext] performBlockAndWait:^{
dispatch_semaphore_wait(phobos_semaphore_t, DISPATCH_TIME_FOREVER); PhobosToBeSendEntitiesCount = 0;
[entities enumerateObjectsUsingBlock:^(PhobosSendDataEntity *obj, NSUInteger idx, BOOL * _Nonnull stop) { [PhobosSendDataEntity MR_truncateAllInContext:[self PhobosContext]];
[obj MR_deleteEntityInContext:PhobosDefaultContext];
}];
dispatch_semaphore_signal(phobos_semaphore_t);
[self saveWithCompletion:nil]; [self saveWithCompletion:nil];
}];
}
#pragma mark - private
/**
* 初始化sdk
*/
+ (void)setupSDK {
// 创建 NSManagedObjectContext,供埋点库访问CoreData库使用
PhobosDefaultContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
// 获取埋点数据的实体
NSURL *modelURL = [bundle URLForResource:@"GMPhobosData" withExtension:@"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
// 创建持久化存储调度器
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
// 创建并关联SQLite数据库文件,如果已经存在则不会重复创建
NSString *dataPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
dataPath = [dataPath stringByAppendingFormat:@"/%@.sqlite",@"GMPhobos"];
[coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:dataPath] options:nil error:nil];
// 设置storeCoordinator
[self PhobosContext].persistentStoreCoordinator = coordinator;
}
/*
* 重置数据库中的数据和待发送数量
*/
+ (void)resetData {
[[self PhobosContext] performBlockAndWait:^{
/** 将上次没有获取到发送结果的数据的状态修改为发送失败,待下次重新发送 */
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = %d", PhobosDataSendStatusSending];
NSArray<PhobosSendDataEntity *> *entities = [self noWaitFetchDataEntitiesWithPredicate:predicate];
[self noWaitUpdateEntities:entities sendStatus:PhobosDataSendStatusError completion:nil];
/** 将发送成功的数据删除 */
NSPredicate *finishPredicate = [NSPredicate predicateWithFormat:@"status = %d", PhobosDataSendStatusFinish];
[PhobosSendDataEntity MR_deleteAllMatchingPredicate:finishPredicate inContext:[self PhobosContext]];
[self saveWithCompletion:nil];
/** 设置未发送数据数量 */
NSPredicate *countPredicate = [NSPredicate predicateWithFormat:@"status = %d or status = %d", PhobosDataSendStatusToBeSend, PhobosDataSendStatusError];
PhobosToBeSendEntitiesCount = [[PhobosSendDataEntity MR_numberOfEntitiesWithPredicate:countPredicate inContext:[self PhobosContext]] integerValue];
}];
}
/**
* 在批量修改和删除时维护PhobosToBeSendEntitiesCount字段
*/
+ (void)updatePhobosCountOfToBeSendEntitiesWithStatus:(PhobosDataSendStatus)sendStatus changeCount:(NSUInteger)changeCount {
if (sendStatus == PhobosDataSendStatusSending) {
PhobosToBeSendEntitiesCount -= changeCount;
} else if (sendStatus == PhobosDataSendStatusError) {
PhobosToBeSendEntitiesCount += changeCount;
} }
} }
+ (void)deleteAllEntities { /**
dispatch_semaphore_wait(phobos_semaphore_t, DISPATCH_TIME_FOREVER); * 不使用同步线程安全方案[NSManagedObjectContext performBlockAndWait]获取谓词相应的数据
[PhobosSendDataEntity MR_truncateAllInContext:PhobosDefaultContext]; * 不对外使用,使用该方法时,需要保障线程同步
dispatch_semaphore_signal(phobos_semaphore_t); */
[self saveWithCompletion:nil]; + (NSArray<PhobosSendDataEntity *> *)noWaitFetchDataEntitiesWithPredicate:(NSPredicate *)predicate {
NSFetchRequest *request = [PhobosSendDataEntity MR_createFetchRequestInContext:[self PhobosContext]];
[request setPredicate:predicate];
NSError *error = nil;
return [[self PhobosContext] executeFetchRequest:request error:&error];
}
/**
* 不使用同步线程安全方案[NSManagedObjectContext performBlockAndWait]去修改实体数据sendStatus
* 不对外使用,使用该方法时,需要保障线程同步
*/
+ (void)noWaitUpdateEntities:(NSArray<PhobosSendDataEntity *> *)entities sendStatus:(PhobosDataSendStatus)sendStatus completion:(MRSaveCompletionHandler)completion {
[self updatePhobosCountOfToBeSendEntitiesWithStatus:sendStatus changeCount:entities.count];
[entities enumerateObjectsUsingBlock:^(PhobosSendDataEntity *obj, NSUInteger idx, BOOL * _Nonnull stop) {
obj.status = sendStatus;
}];
[self saveWithCompletion:completion];
}
+ (NSManagedObjectContext *)PhobosContext {
return PhobosDefaultContext ?: [NSManagedObjectContext MR_defaultContext];
} }
/** /**
* 在保存完成后调用的完成块。如果发生错误,块将以“BOOL”和“NSError”实例的形式传递成功状态。总是在主队列上调用。 * 在保存完成后调用的完成块。如果发生错误,块将以“BOOL”和“NSError”实例的形式传递成功状态。总是在主队列上调用。
*/ */
+ (void)saveWithCompletion:(MRSaveCompletionHandler)completion { + (void)saveWithCompletion:(MRSaveCompletionHandler)completion {
[PhobosDefaultContext MR_saveOnlySelfWithCompletion:completion]; [[self PhobosContext] MR_saveOnlySelfWithCompletion:completion];
} }
@end @end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment