Commit 9f93ec88 authored by yueming lu's avatar yueming lu

数据库添加和常驻线程实现埋点

parent 418086ca
...@@ -439,18 +439,18 @@ ...@@ -439,18 +439,18 @@
); );
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-GMPhobos_Example/Pods-GMPhobos_Example-frameworks.sh", "${PODS_ROOT}/Target Support Files/Pods-GMPhobos_Example/Pods-GMPhobos_Example-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
"${BUILT_PRODUCTS_DIR}/GMCache/GMCache.framework", "${BUILT_PRODUCTS_DIR}/GMCache/GMCache.framework",
"${BUILT_PRODUCTS_DIR}/GMPhobos/GMPhobos.framework", "${BUILT_PRODUCTS_DIR}/GMPhobos/GMPhobos.framework",
"${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework", "${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework",
"${BUILT_PRODUCTS_DIR}/MagicalRecord/MagicalRecord.framework",
"${BUILT_PRODUCTS_DIR}/TMCache/TMCache.framework", "${BUILT_PRODUCTS_DIR}/TMCache/TMCache.framework",
); );
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMCache.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMCache.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMPhobos.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMPhobos.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MagicalRecord.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TMCache.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TMCache.framework",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
......
...@@ -22,7 +22,11 @@ NSString *const MockEventId = @"eventId"; ...@@ -22,7 +22,11 @@ NSString *const MockEventId = @"eventId";
NSString *const MockUserId = @"1"; NSString *const MockUserId = @"1";
NSString *const MockCityId = @"beijing"; NSString *const MockCityId = @"beijing";
@interface GMViewController () @interface GMViewController ()<UITableViewDelegate ,UITableViewDataSource>
{
UITableView *_tableView;
NSArray *_dataSource;
}
@end @end
...@@ -31,23 +35,101 @@ NSString *const MockCityId = @"beijing"; ...@@ -31,23 +35,101 @@ NSString *const MockCityId = @"beijing";
- (void)viewDidLoad - (void)viewDidLoad
{ {
[super viewDidLoad]; [super viewDidLoad];
[self sdk];
#ifdef POD_CONFIGURATION_APP_STORE _dataSource = @[
NSString *url = @"http://log.gmei.com/log/collect"; @"pageView",
#else @"100个线程 * 100数据",
NSString *url = @"http://log.test.igengmei.com/log/collect"; @"计数发送",
#endif @"瞬间发送",
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:PhobosGray]; @"瞬间发送和计数发送",
Phobos *client = [Phobos clientWithAppName:MockAppName channelId:MockChannelId]; @"表中有多少条数据",
[Phobos setSharedClient:client]; @"清空数据"
Phobos.sharedClient.serverAPI = url; ];
[Phobos.sharedClient setLogEnabled:NO]; // 调试打Log模式,看情况开启
Phobos.sharedClient.signingType = PhobosSigningTypeDebug; _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
Phobos.sharedClient.userId = @""; _tableView.delegate = self;
Phobos.sharedClient.getTopController = ^UIViewController * _Nonnull{ _tableView.dataSource = self;
return self; [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
}; [self.view addSubview:_tableView];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _dataSource.count + 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (indexPath.row < _dataSource.count) {
cell.textLabel.text = _dataSource[indexPath.row];
} else {
cell.textLabel.text = [NSString stringWithFormat:@"%ld", indexPath.row];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row >= _dataSource.count) return;
switch (indexPath.row) {
case 0: //pageView
{
for (int i = 0; i < 20; i++) {
[self pageView:i];
}
}
break;
case 1://100个线程 * 100数据"
{
dispatch_queue_t queue = dispatch_queue_create("lym", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 100; i++) {
dispatch_async(queue, ^{
for (int j = 0; j< 100; j++) {
[Phobos track:@"100*100" attributes:@{@"index":@(i)} sendNow:NO];
}
});
}
}
break;
case 2://@"计数发送",
{
for (int i = 0; i< 10000; i++) {
[Phobos track:@"计数发送" attributes:@{@"index":@(i)} sendNow:NO];
}
NSLog(@"&&&&&&&&&&&&&&&&&");
}
break;
case 3://@"瞬间发送",
{
[Phobos track:@"瞬间发送" attributes:@{@"index":@(0)} sendNow:YES];
}
break;
case 4://瞬间发送和计数发送
{
for (int i = 0; i< 100; i++) {
[Phobos track:@"瞬间发送和计数发送" attributes:@{@"index":@(i)} sendNow:i % 9];
}
}
break;
case 5://清空数据
{
[Phobos fetchToBeSendPhobosDataCount];
}
break;
case 6://清空数据
{
[Phobos removeAllPhobosData];
}
break;
default:
break;
}
}
-(void)pageView:(int)index {
NSString *inDate = [PhobosUtil currentTime]; NSString *inDate = [PhobosUtil currentTime];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:[PhobosUtil currentTime] forKey:@"out"]; [dict setObject:[PhobosUtil currentTime] forKey:@"out"];
...@@ -60,36 +142,27 @@ NSString *const MockCityId = @"beijing"; ...@@ -60,36 +142,27 @@ NSString *const MockCityId = @"beijing";
[dict setObject:@"" forKey:@"extra_param"]; [dict setObject:@"" forKey:@"extra_param"];
[dict setObject:@"" forKey:@"referrer_tab_name"]; [dict setObject:@"" forKey:@"referrer_tab_name"];
[dict setObject:@(0) forKey:@"is_push"]; [dict setObject:@(0) forKey:@"is_push"];
// [Phobos track:@"page_view" attributes:dict]; NSString *name = [NSString stringWithFormat:@"page_view-%d", index];
// NSArray *array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey]; [Phobos track:name attributes:dict];
//
// [Phobos track:@"page_view" attributes:dict];
// array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
// for (int i = 0; i < 200; i++) {
// [Phobos track:[NSString stringWithFormat:@"phobos>>>tt-%d", i] attributes:dict sendNow:YES];
// [Phobos track:[NSString stringWithFormat:@"phobos>>>pv-%d", i] attributes:dict sendNow:(arc4random() % 2 == 0)];
// NSUInteger count = [Phobos fetchToBeSendPhobosDataCount];
// NSLog(@"%lu", (unsigned long)count);
// }
// 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)sdk {
swiftVC *vc = [swiftVC new]; #ifdef POD_CONFIGURATION_APP_STORE
[self presentViewController:vc animated:YES completion:nil]; NSString *url = @"http://log.gmei.com/log/collect";
#else
NSString *url = @"http://log.test.igengmei.com/log/collect";
#endif
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:PhobosGray];
Phobos *client = [Phobos clientWithAppName:MockAppName channelId:MockChannelId];
[Phobos setSharedClient:client];
Phobos.sharedClient.serverAPI = url;
[Phobos.sharedClient setLogEnabled:NO]; // 调试打Log模式,看情况开启
Phobos.sharedClient.signingType = PhobosSigningTypeDebug;
Phobos.sharedClient.userId = @"";
Phobos.sharedClient.getTopController = ^UIViewController * _Nonnull{
return self;
};
} }
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end @end
PODS: PODS:
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- GMCache (1.0.1): - GMCache (1.0.1):
- TMCache (= 2.1.0) - TMCache (= 2.1.0)
- GMPhobos (2.0.7): - GMPhobos (2.0.7):
- FMDB
- GMCache - GMCache
- MagicalRecord
- MJExtension - MJExtension
- MagicalRecord (2.3.2):
- MagicalRecord/Core (= 2.3.2)
- MagicalRecord/Core (2.3.2)
- MJExtension (3.2.1) - MJExtension (3.2.1)
- TMCache (2.1.0) - TMCache (2.1.0)
...@@ -18,7 +18,7 @@ SPEC REPOS: ...@@ -18,7 +18,7 @@ SPEC REPOS:
"git@git.wanmeizhensuo.com:gengmeiios/GMSpecs.git": "git@git.wanmeizhensuo.com:gengmeiios/GMSpecs.git":
- GMCache - GMCache
https://github.com/CocoaPods/Specs.git: https://github.com/CocoaPods/Specs.git:
- MagicalRecord - FMDB
- MJExtension - MJExtension
- TMCache - TMCache
...@@ -27,9 +27,9 @@ EXTERNAL SOURCES: ...@@ -27,9 +27,9 @@ EXTERNAL SOURCES:
:path: "../" :path: "../"
SPEC CHECKSUMS: SPEC CHECKSUMS:
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
GMCache: b78d8e46db864405e91d226ce640cc80d966c611 GMCache: b78d8e46db864405e91d226ce640cc80d966c611
GMPhobos: 115e2608cdebcccf445bf95766fee25a4b62153d GMPhobos: eee96b9eb4c381183e01ae71f1df2deefb0ec0b1
MagicalRecord: 53bed74b4323b930992a725be713e53b37d19755
MJExtension: 635f2c663dcb1bf76fa4b715b2570a5710aec545 MJExtension: 635f2c663dcb1bf76fa4b715b2570a5710aec545
TMCache: 95ebcc9b3c7e90fb5fd8fc3036cba3aa781c9bed TMCache: 95ebcc9b3c7e90fb5fd8fc3036cba3aa781c9bed
......
...@@ -26,7 +26,7 @@ Pod::Spec.new do |s| ...@@ -26,7 +26,7 @@ Pod::Spec.new do |s|
s.source_files = 'GMPhobos/Classes/**/*' s.source_files = 'GMPhobos/Classes/**/*'
s.dependency 'GMCache' s.dependency 'GMCache'
s.dependency 'MJExtension' s.dependency 'MJExtension'
s.dependency 'MagicalRecord' s.dependency 'FMDB'
s.library = 'z' s.library = 'z'
s.resource = 'GMPhobos/*.xcdatamodeld' s.resource = 'GMPhobos/*.xcdatamodeld'
......
...@@ -174,7 +174,6 @@ static NewPhobos *_sharedClient; ...@@ -174,7 +174,6 @@ static NewPhobos *_sharedClient;
phobosLog(@"handleAppInForeground"); phobosLog(@"handleAppInForeground");
[self handleSessionStart]; [self handleSessionStart];
[self handleEventDeviceOpened]; [self handleEventDeviceOpened];
[NewPhobos disposeSendDataWithImmediately:NO];
[self handlePVEventAppInForeground]; [self handlePVEventAppInForeground];
} }
...@@ -187,7 +186,6 @@ static NewPhobos *_sharedClient; ...@@ -187,7 +186,6 @@ static NewPhobos *_sharedClient;
phobosLog(@"handleAppInBackgound"); phobosLog(@"handleAppInBackgound");
[self handlePVEventAppInBackgound]; [self handlePVEventAppInBackgound];
[self handleSessionOver]; [self handleSessionOver];
[NewPhobos disposeSendDataWithImmediately:NO];
} }
/** /**
...@@ -408,11 +406,10 @@ static NewPhobos *_sharedClient; ...@@ -408,11 +406,10 @@ static NewPhobos *_sharedClient;
+ (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow currentAPI:(NSString *)currentAPI { + (void)track:(NSString *)eventName attributes:(NSDictionary *)attributes sendNow:(BOOL)sendNow currentAPI:(NSString *)currentAPI {
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 completion:^(BOOL contextDidSave, NSError * _Nullable error) { [[PhobosDataManager sharedPhobosDataManager] insertData:dataDict sendAPI:currentAPI phobosType:eventName immediately:sendNow];
[self disposeSendDataWithImmediately:sendNow];
}];
} @catch (NSException *exception) { } @catch (NSException *exception) {
NSAssert(NO, @"哎呀呀,VALUE不能为NSObject "); NSAssert(NO, @"哎呀呀,VALUE不能为NSObject ");
} }
...@@ -425,39 +422,26 @@ static NewPhobos *_sharedClient; ...@@ -425,39 +422,26 @@ static NewPhobos *_sharedClient;
*/ */
+ (void)trackSessionOverWithAttributes:(NSDictionary *)attributes { + (void)trackSessionOverWithAttributes:(NSDictionary *)attributes {
NSDictionary *dataDict = [_sharedClient prepareDictionaryForEvent:@"on_app_session_over" attributes:attributes]; NSDictionary *dataDict = [_sharedClient prepareDictionaryForEvent:@"on_app_session_over" attributes:attributes];
[PhobosDataManager insertData:dataDict sendAPI:_sharedClient.serverAPI completion:nil]; [[PhobosDataManager sharedPhobosDataManager] insertData:dataDict sendAPI:_sharedClient.serverAPI phobosType:@"on_app_session_over" immediately:YES];
[self disposeSendDataWithImmediately:YES];
} }
/**
* 处理发送数据
*/
+ (void)disposeSendDataWithImmediately:(BOOL)immediately {
NSInteger count = [PhobosDataManager fetchCountOfToBeSendEntities];
if (immediately || count >= PhobosShardCount) {
NSArray<PhobosSendDataEntity *> *entities = [PhobosDataManager fetchToBeSendDataEntitiesAndUpdateWithSendStatus:PhobosDataSendStatusSending];
[PhobosSendManager sendDataWithEntities:entities completion:^(NSArray<PhobosSendDataEntity *> * _Nonnull finishEntities, NSInteger code) {
[PhobosDataManager updateDataEntities:finishEntities sendStatus:(code == 200 ? PhobosDataSendStatusFinish : PhobosDataSendStatusError) completion:nil];
}];
}
}
@end @end
@implementation NewPhobos (UtilTest) @implementation NewPhobos (UtilTest)
/** 获取所有非立即发送埋点数量 */ ///** 获取所有非立即发送埋点数量 */
+ (NSUInteger)fetchToBeSendPhobosDataCount { + (NSUInteger)fetchToBeSendPhobosDataCount {
return [PhobosDataManager fetchCountOfToBeSendEntities]; return [[PhobosDataManager sharedPhobosDataManager] messageCount] ;
}
/** 获取待发送埋点数据, 用同步来保障异步获取数据 */
+ (NSArray *)fetchToBeSendPhobosData {
return [PhobosDataManager fetchToBeSendDataEntities];
} }
///** 获取待发送埋点数据, 用同步来保障异步获取数据 */
//+ (NSArray *)fetchToBeSendPhobosData {
// return [PhobosDataManager fetchToBeSendDataEntities];
//}
//
/** 清除待发送埋点数据缓存 */ /** 清除待发送埋点数据缓存 */
+ (void)removeAllPhobosData { + (void)removeAllPhobosData {
[PhobosDataManager deleteAllEntities]; [[PhobosDataManager sharedPhobosDataManager] removeAll];
} }
@end @end
//
// PhobosDataManager.h
// GMCache
//
// Created by Locus on 2020/1/21.
//
#import <Foundation/Foundation.h>
#import <MagicalRecord/MagicalRecord.h>
#import "PhobosSendDataEntity+CoreDataClass.h"
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, PhobosDataSendStatus) {
PhobosDataSendStatusToBeSend = 1, // 待发送数据
PhobosDataSendStatusSending = 2, // 发送中数据
PhobosDataSendStatusFinish = 3, // 发送完成数据
PhobosDataSendStatusError = 4, // 发送失败数据
};
@interface PhobosDataManager : NSObject
/**
* 获取待发送和发送失败的数据数量
*/
+ (NSUInteger)fetchCountOfToBeSendEntities;
/**
* 获取待发送数据,包含待发送数据和发送失败数据
* predicate 通过谓词获取相应的数据
*/
+ (NSArray<PhobosSendDataEntity *> *)fetchToBeSendDataEntities;
+ (NSArray<PhobosSendDataEntity *> *)fetchDataEntitiesWithPredicate:(NSPredicate *)predicate;
/**
* 获取待发送数据,包含待发送数据和发送失败数据, 并修改状态为sendStatus
*/
+ (NSArray<PhobosSendDataEntity *> *)fetchToBeSendDataEntitiesAndUpdateWithSendStatus:(PhobosDataSendStatus)sendStatus;
/**
* 插入埋点数据
* data 埋点参数
* sendAPI 数据接收的服务器API
* completion 插入数据库成功后的回调方法,在保存完成后调用的完成块。如果发生错误,块将以“BOOL”和“NSError”实例的形式传递成功状态。总是在主队列上调用。
* 该方法调用完成,fetch方法获取相应的数据就可获取到,不需要等completion回调。
*/
+ (void)insertData:(NSDictionary *)data sendAPI:(NSString *)sendAPI completion:(MRSaveCompletionHandler)completion;
/**
* 修改埋点数据
* entities 需要修改的实体
* sendStatus 需要修改为的状态,
* completion 插入数据库成功后的回调方法,在保存完成后调用的完成块。如果发生错误,块将以“BOOL”和“NSError”实例的形式传递成功状态。总是在主队列上调用。
* 该方法调用完成,fetch方法获取相应的数据就可获取到,不需要等completion回调。
*/
+ (void)updateDataEntities:(NSArray<PhobosSendDataEntity *> *)entities sendStatus:(PhobosDataSendStatus)sendStatus completion:(MRSaveCompletionHandler)completion;
/**
* 删除所有数据
* 仅限单元测试使用
*/
+ (void)deleteAllEntities;
@end
NS_ASSUME_NONNULL_END
//
// PhobosDataManager.m
// GMCache
//
// Created by Locus on 2020/1/21.
//
#import "PhobosDataManager.h"
#import "PhobosSendManager.h"
#import "PhobosConfig.h"
#import "PhobosUtil.h"
#import <MJExtension/MJExtension.h>
#import <mach/mach_time.h>
@implementation PhobosDataManager
static NSManagedObjectContext *PhobosDefaultContext;
static NSUInteger PhobosToBeSendEntitiesCount = 0;
+ (void)initialize {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self setupSDK];
[self resetData];
});
}
+ (NSUInteger)fetchCountOfToBeSendEntities {
return PhobosToBeSendEntitiesCount;
}
+ (NSArray<PhobosSendDataEntity *> *)fetchToBeSendDataEntities {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = %d or status = %d", PhobosDataSendStatusToBeSend, PhobosDataSendStatusError];
return [self fetchDataEntitiesWithPredicate:predicate];
}
+ (NSArray<PhobosSendDataEntity *> *)fetchDataEntitiesWithPredicate:(NSPredicate *)predicate {
__block NSArray *results = nil;
[[self PhobosContext] performBlockAndWait:^{
results = [self noWaitFetchDataEntitiesWithPredicate:predicate];
}];
return results;
}
+ (NSArray<PhobosSendDataEntity *> *)fetchToBeSendDataEntitiesAndUpdateWithSendStatus:(PhobosDataSendStatus)sendStatus {
__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 {
if (!sendAPI || [sendAPI isEqualToString:@""] || !data) {
return;
}
[[self PhobosContext] performBlockAndWait:^{
PhobosSendDataEntity *entity = [PhobosSendDataEntity MR_createEntityInContext:[self PhobosContext]];
entity.data = [data mj_JSONData];
entity.api = sendAPI;
entity.status = PhobosDataSendStatusToBeSend;
entity.id = mach_absolute_time();
PhobosToBeSendEntitiesCount++;
[self saveWithCompletion:completion];
}];
}
+ (void)updateDataEntities:(NSArray<PhobosSendDataEntity *> *)entities sendStatus:(PhobosDataSendStatus)sendStatus completion:(MRSaveCompletionHandler)completion {
if (entities.count > 0) {
[[self PhobosContext] performBlockAndWait :^{
[self noWaitUpdateEntities:entities sendStatus:sendStatus completion:completion];
}];
}
}
+ (void)deleteAllEntities {
[[self PhobosContext] performBlockAndWait:^{
PhobosToBeSendEntitiesCount = 0;
[PhobosSendDataEntity MR_truncateAllInContext:[self PhobosContext]];
[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;
}
}
/**
* 不使用同步线程安全方案[NSManagedObjectContext performBlockAndWait]获取谓词相应的数据
* 不对外使用,使用该方法时,需要保障线程同步
*/
+ (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”实例的形式传递成功状态。总是在主队列上调用。
*/
+ (void)saveWithCompletion:(MRSaveCompletionHandler)completion {
[[self PhobosContext] MR_saveOnlySelfWithCompletion:completion];
}
@end
//
// GMPhobosSqulitModel.h
// GMPhobos
//
// Created by edz on 2020/6/18.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM(int, PhobosDataSendStatus) {
PhobosDataSendStatusToBeSend = 1, // 待发送数据
PhobosDataSendStatusSending = 2, // 发送中数据
PhobosDataSendStatusFinish = 3, // 发送完成数据
PhobosDataSendStatusError = 4, // 发送失败数据
};
@interface GMPhobosSqulitModel : NSObject
/// 唯一标识(用于筛选)
@property (nonatomic, strong) NSString *messageId;
/// 埋点类型
@property (nonatomic, strong) NSString *phobosType;
/// 内容
@property (nonatomic, strong) NSString *data;
/// 路径
@property (nonatomic, strong) NSString *api;
/// 数据状态
@property (nonatomic, assign) PhobosDataSendStatus status;
///是否是立刻发的埋点
@property (nonatomic, assign) BOOL immediately;
+ (GMPhobosSqulitModel *)modelOfDict:(NSDictionary *)data
type:(NSString *)phobosType
urlApi:(NSString *)urlapi
immediately:(BOOL)status;
@end
//
// GMPhobosSqulitModel.m
// GMPhobos
//
// Created by edz on 2020/6/18.
//
#import "GMPhobosSqulitModel.h"
#import <mach/mach_time.h>
@implementation GMPhobosSqulitModel
+ (GMPhobosSqulitModel *)modelOfDict:(NSDictionary *)data
type:(NSString *)phobosType
urlApi:(NSString *)urlapi
immediately:(BOOL)status {
GMPhobosSqulitModel *model = [GMPhobosSqulitModel new];
model.data = [GMPhobosSqulitModel dictionaryToJsonString:data];
NSTimeInterval time = [[NSDate date] timeIntervalSince1970] * 1000;
model.messageId = [NSString stringWithFormat:@"%.f*%lld", time, mach_absolute_time()];
model.status = PhobosDataSendStatusToBeSend;
model.phobosType = phobosType;
model.api = urlapi;
model.immediately = status;
return model;
}
+ (NSString *)dictionaryToJsonString:(NSDictionary *)dict
{
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];
if (error) {
return nil;
}
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
@end
// //
// PhobosSendDataEntity+CoreDataClass.h // GMPhobosThread.h
// GMPhobos // GMPhobos
// //
// Created by Locus on 2020/3/9. // Created by edz on 2020/6/21.
//
// //
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@interface PhobosSendDataEntity : NSManagedObject @interface GMPhobosThread : NSThread
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END
#import "PhobosSendDataEntity+CoreDataProperties.h"
//
// GMPhobosThread.m
// GMPhobos
//
// Created by edz on 2020/6/21.
//
#import "GMPhobosThread.h"
@implementation GMPhobosThread
- (void)dealloc {
NSLog(@"%s", __func__);
}
@end
//
// GMSQliteManager.h
// GMSQlite
//
// Created by 卢悦明 on 2020/6/10.
// Copyright © 2020 卢悦明. All rights reserved.
//
#import <Foundation/Foundation.h>
// 数据库中常见的几种类型
#define SQL_TEXT @"TEXT" //文本
#define SQL_INTEGER @"INTEGER" //int long integer ...
#define SQL_REAL @"REAL" //浮点
#define SQL_BLOB @"BLOB" //data
@interface GMSQliteManager : NSObject
#pragma mark - 创建数据库
/// 创建数据库的单利方法
+ (instancetype)sharedSQliteManager;
#pragma mark - 创建表
/// 创建表
/// @param tableName 名称
/// @param modelClass 类对象
- (BOOL)gm_createTable:(NSString *)tableName model:(Class)modelClass;
/// 创建表
/// @param tableName 名称
/// @param dict key 为键, value为存储类型
- (BOOL)gm_createTable:(NSString *)tableName dict:(NSDictionary *)dict;
#pragma mark - 插入操作
///字典插入
- (BOOL)gm_insertTable:(NSString *)tableName dict:(NSDictionary *)dict;
/// 模型插入
- (BOOL)gm_insertTable:(NSString *)tableName model:(NSObject *)model;
/**
批量插入或更改
@param dicOrModelArray 要insert/update数据的数组,也可以将model和dictionary混合装入array
@return 返回的数组存储未插入成功的下标,数组中元素类型为NSNumber
*/
- (NSArray *)gm_insertTable:(NSString *)tableName dicOrModelArray:(NSArray *)dicOrModelArray;
#pragma mark - 删除操作
/// 删除表中某些元素,
/// @param tableName 表的名称
/// @param format 条件语句, 如:@"where name = '小李'"
- (BOOL)gm_deleteTable:(NSString *)tableName whereFormat:(NSString *)format;
///删除表
- (BOOL)gm_deleteTable:(NSString *)tableName;
///清空表
- (BOOL)gm_deleteAllDataFromTable:(NSString *)tableName;
#pragma mark - 修改操作
/// 根据条件更改表中数据
/// @param tableName 名称
/// @param parameters 要更改的数据,可以是model或dictionary(格式:@{@"name":@"张三"})
/// @param format 条件语句, 如:@"where name = '小李'"
- (BOOL)gm_updateTable:(NSString *)tableName
dicOrModel:(id)parameters
whereFormat:(NSString *)format;
#pragma mark - 查找操作
/**
查找: 根据条件查找表中数据
@param tableName 表的名称
@param filterArray 过滤字段
@param cls [Persen class]
@param format 条件语句, 如:@"where name = '小李'",
@return 将结果存入array, @[@{@"age":@"", @"name":@""}]
*/
- (NSArray *)gm_lookupTable:(NSString *)tableName
filterArray:(NSArray *)filterArray
objectClass:(Class)cls
whereFormat:(NSString *)format;
- (NSArray *)gm_lookupTable:(NSString *)tableName
keyArray:(NSArray *)keyArray
whereFormat:(NSString *)format;
#pragma mark - 辅助接口
///是否存在表
- (BOOL)gm_isExistTable:(NSString *)tableName;
/// 表中共有多少条数据
/// @param tableName 表的名称
/// @param format 筛选条件(where name = '小李'), 如果没有条件可以传nil
- (int)gm_tableItemCount:(NSString *)tableName whereFormat:(NSString *)format;
/// 返回表中的字段名
- (NSArray *)gm_columnNameArray:(NSString *)tableName;
/// `关闭数据库
- (void)close;
/// 打开数据库 (每次shareDatabase系列操作时已经open,当调用close后若进行db操作需重新open或调用shareDatabase)
- (void)open;
/**
增加新字段, 在建表后还想新增字段,可以在原建表model或新model中新增对应属性,然后传入即可新增该字段,该操作已在事务中执行
@param tableName 表的名称
@param parameters dictionary格式为@{@"newname":@"TEXT"}
@return 是否成功
*/
- (BOOL)gm_alterTable:(NSString *)tableName keyDict:(NSDictionary *)parameters;
// ============================= 线程安全操作 ===============================
#pragma mark - 线程安全的处理
/**
将操作语句放入block中即可保证线程安全, 如:
Person *p = [[Person alloc] init];
p.name = @"小李";
[db gm_inDatabase:^{
[db gm_insertTable:@"users" dicOrModel:p];
}];
*/
- (void)gm_inDatabase:(void (^)(void))block;
/**
事务: 将操作语句放入block中可执行回滚操作(*rollback = YES;)
Person *p = [[Person alloc] init];
p.name = @"小李";
for (int i=0,i < 1000,i++) {
[db gm_inTransaction:^(BOOL *rollback) {
BOOL flag = [db gm_insertTable:@"users" dicOrModel:p];
if (!flag) {
*rollback = YES; //只要有一次不成功,则进行回滚操作
return;
}
}];
}
*/
- (void)gm_inTransaction:(void(^)(BOOL *rollback))block;
@end
This diff is collapsed.
//
// PhobosDataManager.h
// GMCache
//
// Created by Locus on 2020/1/21.
//
#import <Foundation/Foundation.h>
@interface PhobosDataManager : NSObject
/// 初始化方法(单利)
+ (PhobosDataManager *)sharedPhobosDataManager;
/// 插入数据的方法 (如果返回的是NO,就会直接把数据发送出去,不放到数据控中)
/// @param data 埋点数据dict
/// @param sendAPI 发送的url
/// @param phoboType 埋点类型
/// @param status 是否是立即发送的埋点
- (void)insertData:(NSDictionary *)data
sendAPI:(NSString *)sendAPI
phobosType:(NSString *)phoboType
immediately:(BOOL)status;
- (void)removeAll;
- (int)messageCount;
@end
//
// PhobosDataManager.m
// GMCache
//
// Created by Locus on 2020/1/21.
//
#import "PhobosDataManager.h"
#import "PhobosSendManager.h"
#import "PhobosConfig.h"
#import "PhobosUtil.h"
#import "GMSQliteManager.h"
#import "GMPhobosSqulitModel.h"
#import <MJExtension/MJExtension.h>
#import "GMPhobosThread.h"
#define KtableName @"phobosTable"
@interface PhobosDataManager ()
//数据库操作对象(单利)
@property (nonatomic, strong) GMSQliteManager *squlitManager;
/// 记录没有发送的数据个数(大于50 就要发送数据)
@property (nonatomic, assign) NSInteger messageCont;
/// runloop线程,用来处理埋点的数据
@property (nonatomic, strong) GMPhobosThread *phobosThread;
@end
@implementation PhobosDataManager
static PhobosDataManager *dataManager;
+ (PhobosDataManager *)sharedPhobosDataManager {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
dataManager = [[PhobosDataManager alloc] init];
});
return dataManager;
}
- (instancetype)init {
self = [super init];
if (self) {
[self setupSDK];
}
return self;
}
- (void)removeAll {
[self performSelector:@selector(remove) onThread:_phobosThread withObject:nil waitUntilDone:YES];
}
- (void)remove {
bool status = [_squlitManager gm_deleteAllDataFromTable:KtableName];
NSLog(@"清空表格数状态:%d",status);
}
- (int)messageCount {
int count = [_squlitManager gm_tableItemCount:KtableName whereFormat:nil];
NSLog(@"数据总数:%d",count);
return count;
}
#pragma mark - 初始化
- (void)setupSDK {
_squlitManager = [GMSQliteManager sharedSQliteManager];
//创建表格
bool status = [_squlitManager gm_createTable:KtableName model:[GMPhobosSqulitModel class]];
//初始化线程和runloop
__weak typeof(self) weakSelf = self;
_phobosThread = [[GMPhobosThread alloc] initWithBlock:^{
[[NSRunLoop currentRunLoop] addPort:[NSPort new] forMode:NSDefaultRunLoopMode];
while (weakSelf) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}];
_phobosThread.name = @"phobosThread";
[_phobosThread start];
//修改数据
[self performSelector:@selector(resetData) onThread:_phobosThread withObject:nil waitUntilDone:NO];
}
#pragma mark - 方法只用在APP启动的时候
- (void)resetData {
/** 将上次没有获取到发送结果的数据的状态修改为发送失败,待下次重新发送 */
NSString *whereStr = [NSString stringWithFormat:@"where status = %d", PhobosDataSendStatusSending];
[_squlitManager gm_updateTable:KtableName dicOrModel:@{@"status":@(PhobosDataSendStatusError)} whereFormat:whereStr];
/** 将发送成功的数据删除 */
NSString *whereDelet = [NSString stringWithFormat:@"where status = %d", PhobosDataSendStatusFinish];
[_squlitManager gm_deleteTable:KtableName whereFormat:whereDelet];
/** 设置未发送数据数量 */
NSString *whereCount = [NSString stringWithFormat:@"where status = %d or status = %d", PhobosDataSendStatusToBeSend, PhobosDataSendStatusError];
_messageCont = [_squlitManager gm_tableItemCount:KtableName whereFormat:whereCount];
}
#pragma mark - 插入数据
- (void)insertData:(NSDictionary *)data
sendAPI:(NSString *)sendAPI
phobosType:(NSString *)phoboType
immediately:(BOOL)status {
if (!sendAPI || [sendAPI isEqualToString:@""] || !data) return;
GMPhobosSqulitModel *squlitModel = [GMPhobosSqulitModel modelOfDict:data type:phoboType urlApi:sendAPI immediately:status];
[self performSelector:@selector(insertModel:) onThread:_phobosThread withObject:squlitModel waitUntilDone:NO];
}
- (void)insertModel:(GMPhobosSqulitModel *)squlitModel {
BOOL insertType = [_squlitManager gm_insertTable:KtableName model:squlitModel];
if (!insertType) {//如果插入失败,就直接发送给服务器
[self sendModelArray:@[squlitModel]];
} else if (squlitModel.immediately) {//需要立刻发送的埋点
[self disposeSendDataWithImmediately:YES];
} else {//插入到数据中
self.messageCont++;
[self disposeSendDataWithImmediately:NO];
}
NSLog(@"插入数状态%d count:%d", insertType,_messageCont);
}
#pragma mark - 获取待发送数据并修改状态为“发送”
- (NSArray *)fetchToBeSendDataEntitiesAndUpdateWithSendStatus {
NSString *where = [NSString stringWithFormat:@"where status = %d or status = %d", PhobosDataSendStatusToBeSend, PhobosDataSendStatusError];
/**获取待发送的数据*/
NSArray *array = [_squlitManager gm_lookupTable:KtableName filterArray:nil objectClass:[GMPhobosSqulitModel class] whereFormat:where];
/**将待发送的数据修改为“发送中”*/
[_squlitManager gm_updateTable:KtableName dicOrModel:@{@"status":@(PhobosDataSendStatusSending)} whereFormat:where];
return array;
}
#pragma mark - 是否需要发送数据
- (void)disposeSendDataWithImmediately:(BOOL)status {
NSString *where = [NSString stringWithFormat:@"where status = %d or status = %d", PhobosDataSendStatusToBeSend, PhobosDataSendStatusError];
_messageCont = [_squlitManager gm_tableItemCount:KtableName whereFormat:where];
if (status || _messageCont >= PhobosShardCount) {
NSArray *array = [self fetchToBeSendDataEntitiesAndUpdateWithSendStatus];
NSMutableArray *entities = [GMPhobosSqulitModel mj_objectArrayWithKeyValuesArray:array];
[self sendModelArray:entities];
}
}
- (void)sendModelArray:(NSArray<GMPhobosSqulitModel *> *)entities {
NSLog(@"发送*******%lld", entities.count);
[PhobosSendManager sendDataWithEntities:entities completion:^(NSArray<GMPhobosSqulitModel *> *finishEntities, NSInteger code) {
SEL selelct = code == 200 ? @selector(sendSuccess:) :@selector(sendError:);
[self performSelector:selelct onThread:_phobosThread withObject:finishEntities waitUntilDone:NO];
}];
}
#pragma mark - 上报数据成功
- (void)sendSuccess:(NSArray<GMPhobosSqulitModel*> *)entities {
for (GMPhobosSqulitModel *model in entities) {
NSString *whereStr = [NSString stringWithFormat:@"where messageId = '%@'", model.messageId];
bool status = [_squlitManager gm_deleteTable:KtableName whereFormat:whereStr];
NSLog(@"删除状态:%d", status);
}
}
#pragma mark - 上报数据失败
- (void)sendError:(NSArray<GMPhobosSqulitModel*> *)entities {
for (GMPhobosSqulitModel *model in entities) {
NSString *whereStr = [NSString stringWithFormat:@"where messageId = '%@'", model.messageId];
bool status = [_squlitManager gm_updateTable:KtableName
dicOrModel: @{@"status":@(PhobosDataSendStatusError)}
whereFormat:whereStr];
NSLog(@"发送失败后修改状态:%d",status);
}
}
@end
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
// //
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "PhobosDataManager.h" #import "GMPhobosSqulitModel.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
...@@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN ...@@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN
/** /**
* 发送数据 * 发送数据
*/ */
+ (void)sendDataWithEntities:(NSArray<PhobosSendDataEntity *> *)needSendData completion:(nullable void(^)(NSArray<PhobosSendDataEntity *> *finishEntities, NSInteger code))completion; + (void)sendDataWithEntities:(NSArray<GMPhobosSqulitModel *> *)needSendData completion:(nullable void(^)(NSArray<GMPhobosSqulitModel *> *finishEntities, NSInteger code))completion;
@end @end
......
...@@ -40,24 +40,27 @@ ...@@ -40,24 +40,27 @@
}]; }];
} }
NSString *exposureAPI = [GMExposureManager sharedManager].uploadExposureAPI; NSString *exposureAPI = [GMExposureManager sharedManager].uploadExposureAPI;
NSArray *exposureArray = [GMCache fetchObjectAtDocumentPathWithkey:[PhobosUtil MD5String:exposureAPI]]; if (exposureAPI) {
NSString *str = [PhobosUtil MD5String:exposureAPI];
NSArray *exposureArray = [GMCache fetchObjectAtDocumentPathWithkey:str];
if (exposureArray.count > 0) { if (exposureArray.count > 0) {
/** 获取非灰度下发送失败的埋点,进行发送 */ /** 获取非灰度下发送失败的埋点,进行发送 */
[self sendDataArray:exposureArray currentAPI:exposureAPI success:^(NSInteger code) { [self sendDataArray:exposureArray currentAPI:exposureAPI success:^(NSInteger code) {
if (code = 200) { if (code == 200) {
[GMCache removeObjectAtDocumentPathWithkey:[PhobosUtil MD5String:exposureAPI]]; [GMCache removeObjectAtDocumentPathWithkey:[PhobosUtil MD5String:exposureAPI]];
} }
}]; }];
} }
}
} }
+ (void)sendDataWithEntities:(NSArray<PhobosSendDataEntity *> *)sendDataEntities completion:(void (^)(NSArray<PhobosSendDataEntity *> * _Nonnull, NSInteger))completion { + (void)sendDataWithEntities:(NSArray<GMPhobosSqulitModel *> *)sendDataEntities completion:(void (^)(NSArray<GMPhobosSqulitModel *> * _Nonnull, NSInteger))completion {
if (sendDataEntities.count == 0) { if (sendDataEntities.count == 0) {
return; return;
} else if (sendDataEntities.count > PhobosMaxSendCount) { } else if (sendDataEntities.count > PhobosMaxSendCount) {
/** 如果数据超过 PhobosMaxSendCount 数据规模,进行拆分,分批发送,默认100条 */ /** 如果数据超过 PhobosMaxSendCount 数据规模,进行拆分,分批发送,默认100条 */
NSMutableArray *temp = [NSMutableArray arrayWithCapacity:PhobosMaxSendCount]; NSMutableArray *temp = [NSMutableArray arrayWithCapacity:PhobosMaxSendCount];
[sendDataEntities enumerateObjectsUsingBlock:^(PhobosSendDataEntity * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { [sendDataEntities enumerateObjectsUsingBlock:^(GMPhobosSqulitModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (temp.count >= PhobosMaxSendCount) { if (temp.count >= PhobosMaxSendCount) {
// 会调用当前方法,但数据规模不会满足 > PhobosMaxSendCount,不会让数据走到下面的发送,拆分完成 会执行return // 会调用当前方法,但数据规模不会满足 > PhobosMaxSendCount,不会让数据走到下面的发送,拆分完成 会执行return
[self sendDataWithEntities:temp completion:completion]; [self sendDataWithEntities:temp completion:completion];
...@@ -69,16 +72,16 @@ ...@@ -69,16 +72,16 @@
} }
NSMutableDictionary *sendDataMap = [NSMutableDictionary new]; NSMutableDictionary *sendDataMap = [NSMutableDictionary new];
// 将相同api的数据合并 // 将相同api的数据合并
[sendDataEntities enumerateObjectsUsingBlock:^(PhobosSendDataEntity *obj, NSUInteger idx, BOOL * _Nonnull stop) { [sendDataEntities enumerateObjectsUsingBlock:^(GMPhobosSqulitModel *obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSMutableArray *sendData = sendDataMap[obj.api] ?: [NSMutableArray new]; NSMutableArray *sendData = sendDataMap[obj.api] ?: [NSMutableArray new];
[sendData addObject:obj]; [sendData addObject:obj];
[sendDataMap setValue:sendData forKey:obj.api]; [sendDataMap setValue:sendData forKey:obj.api];
}]; }];
// 将实体转为待发送数据,取出PhobosSendDataEntity中的data,并发送 // 将实体转为待发送数据,取出PhobosSendDataEntity中的data,并发送
[sendDataMap enumerateKeysAndObjectsUsingBlock:^(NSString *api, NSArray<PhobosSendDataEntity *> *entities, BOOL * _Nonnull stop) { [sendDataMap enumerateKeysAndObjectsUsingBlock:^(NSString *api, NSArray<GMPhobosSqulitModel *> *entities, BOOL * _Nonnull stop) {
NSMutableArray *sendDatas = [NSMutableArray new]; NSMutableArray *sendDatas = [NSMutableArray new];
[entities enumerateObjectsUsingBlock:^(PhobosSendDataEntity *obj, NSUInteger idx, BOOL * _Nonnull stop) { [entities enumerateObjectsUsingBlock:^(GMPhobosSqulitModel *obj, NSUInteger idx, BOOL * _Nonnull stop) {
id data = [obj.data mj_JSONObject]; id data = [obj.data mj_JSONObject];
if (data) { if (data) {
[sendDatas addObject:data]; [sendDatas addObject:data];
......
//
// PhobosSendDataEntity+CoreDataClass.m
// GMPhobos
//
// Created by Locus on 2020/3/9.
//
//
#import "PhobosSendDataEntity+CoreDataClass.h"
@implementation PhobosSendDataEntity
@end
//
// PhobosSendDataEntity+CoreDataProperties.h
// GMPhobos
//
// Created by Locus on 2020/3/9.
//
//
#import "PhobosSendDataEntity+CoreDataClass.h"
NS_ASSUME_NONNULL_BEGIN
@interface PhobosSendDataEntity (CoreDataProperties)
+ (NSFetchRequest<PhobosSendDataEntity *> *)fetchRequest;
@property (nonatomic) int64_t id;
@property (nullable, nonatomic, retain) NSData *data;
@property (nullable, nonatomic, copy) NSString *api;
@property (nonatomic) int16_t status;
@end
NS_ASSUME_NONNULL_END
//
// PhobosSendDataEntity+CoreDataProperties.m
// GMPhobos
//
// Created by Locus on 2020/3/9.
//
//
#import "PhobosSendDataEntity+CoreDataProperties.h"
@implementation PhobosSendDataEntity (CoreDataProperties)
+ (NSFetchRequest<PhobosSendDataEntity *> *)fetchRequest {
return [NSFetchRequest fetchRequestWithEntityName:@"PhobosSendDataEntity"];
}
@dynamic id;
@dynamic data;
@dynamic api;
@dynamic status;
@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