1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
//
// 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 "GMPhobosPageViewModel.h"
#import <MJExtension/MJExtension.h>
#import "GMPhobosThread.h"
#import "GMPhobosTool.h"
#define KtableName @"phobosTable"
#define KPageViewTableName @"pageViewTable"
#define KName @"tableName"
#define KClass @"class"
@interface PhobosDataManager ()
//数据库操作对象(单利)
@property (nonatomic, strong) GMSQliteManager *squlitManager;
/// 记录没有发送的数据个数(大于50 就要发送数据)
@property (nonatomic, assign) NSInteger messageCont;
/// runloop线程,用来处理埋点的数据
@property (nonatomic, strong) GMPhobosThread *phobosThread;
@property (nonatomic, strong) NSArray *tableMessageArray;
@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) {
_tableMessageArray = @[
@{
KName:KtableName,
KClass:[GMPhobosSqulitModel class]
},
@{
KName:KPageViewTableName,
KClass:[GMPhobosPageViewModel class]
}
];
[self setupSDK];
}
return self;
}
- (void)removeAll {
[self performSelector:@selector(remove) onThread:_phobosThread withObject:nil waitUntilDone:YES];
}
- (void)remove {
bool status = [_squlitManager gm_deleteAllDataFromTable:KtableName];
bool status1 = [_squlitManager gm_deleteAllDataFromTable:KPageViewTableName];
NSLog(@"清空表格数状态-KtableName:%d KPageViewTableName:%d",status,status1);
}
- (int)messageCount {
int count = [_squlitManager gm_tableItemCount:KtableName whereFormat:nil];
int count1 = [_squlitManager gm_tableItemCount:KPageViewTableName whereFormat:nil];
NSLog(@"数据总数:%d - KtableName:%d KPageViewTableName:%d", count + count1, count, count1);
return count;
}
#pragma mark - 初始化
- (void)setupSDK {
//创建数据库和表格
_squlitManager = [[GMSQliteManager alloc] init];
for (NSDictionary *dict in _tableMessageArray) {
[_squlitManager gm_createTable:dict[KName] model:dict[KClass]];
}
//初始化线程和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 {
for (NSDictionary *dict in _tableMessageArray) {
/** 将上次没有获取到发送结果的数据的状态修改为发送失败,待下次重新发送 */
NSString *whereStr = [NSString stringWithFormat:@"where status = %d", PhobosDataSendStatus_send];
[_squlitManager gm_updateTable:dict[KName] dicOrModel:@{@"status":@(PhobosDataSendStatus_error)} whereFormat:whereStr];
/** 将发送成功的数据删除 */
NSString *whereDelet = [NSString stringWithFormat:@"where status = %d", PhobosDataSendStatus_finish];
[_squlitManager gm_deleteTable:dict[KName] whereFormat:whereDelet];
}
}
#pragma mark - 插入数据
- (void)insertData:(NSDictionary *)data
sendAPI:(NSString *)sendAPI
phobosType:(NSString *)phoboType
immediately:(BOOL)status {
if (!sendAPI || [sendAPI isEqualToString:@""] || !data) return;
if ([phoboType containsString:@"page_view"]) {
GMPhobosPageViewModel *squlitModel = [GMPhobosPageViewModel pageViewModelOfDict:data type:phoboType urlApi:sendAPI tableName:KPageViewTableName immediately:status];
[self performSelector:@selector(insertModel:) onThread:_phobosThread withObject:squlitModel waitUntilDone:NO];
} else {
GMPhobosSqulitModel *squlitModel = [GMPhobosSqulitModel modelOfDict:data type:phoboType urlApi:sendAPI tableName:KtableName immediately:status];
[self performSelector:@selector(insertModel:) onThread:_phobosThread withObject:squlitModel waitUntilDone:NO];
}
}
- (void)insertModel:(GMPhobosSqulitModel *)squlitModel {
BOOL insertType = [_squlitManager gm_insertTable:squlitModel.table_name model:squlitModel];
if (!insertType) {//如果插入失败,就直接发送给服务器
[self sendModelArray:@[squlitModel]];
} else if (squlitModel.immediately) {//需要立刻发送的埋点
[self disposeSendDataWithImmediately:YES];
} else {//插入到数据中
self.messageCont++;
[self disposeSendDataWithImmediately:NO];
}
NSLog(@"插入%@状态%d count:%d",squlitModel.phobos_type, insertType,_messageCont);
}
#pragma mark - 获取待发送数据并修改状态为“发送”
- (NSMutableArray *)fetchToBeSendDataEntitiesAndUpdateWithSendStatus {
NSString *where = [NSString stringWithFormat:@"where status = %d or status = %d", PhobosDataSendStatus_wait, PhobosDataSendStatus_error];
NSMutableArray *array = [NSMutableArray array];
for (NSDictionary *dict in _tableMessageArray) {
/**获取待发送的数据*/
NSArray *sub = [_squlitManager gm_lookupTable:dict[KName] filterArray:nil objectClass:dict[KClass] whereFormat:where];
[array addObjectsFromArray:sub];
/**将待发送的数据修改为“发送中”*/
[_squlitManager gm_updateTable:dict[KName] dicOrModel:@{@"status":@(PhobosDataSendStatus_send)} whereFormat:where];
}
return array;
}
//获取待发送的数据个数
- (int)getAllTabelNeedSendMessageCount {
int count = 0;
NSString *where = [NSString stringWithFormat:@"where status = %d or status = %d", PhobosDataSendStatus_wait, PhobosDataSendStatus_error];
for (NSDictionary *dict in _tableMessageArray) {
int tableCount = [_squlitManager gm_tableItemCount:dict[KName] whereFormat:where];
count += tableCount;
}
return count;
}
#pragma mark - 是否需要发送数据
- (void)disposeSendDataWithImmediately:(BOOL)status {
if (!status) {
_messageCont = [self getAllTabelNeedSendMessageCount];
if (_messageCont < PhobosShardCount) return;
}
/**
能走到下面说明“满足上报埋点条件 status == yes || _messageCont >= PhobosShardCount”
*/
NSMutableArray *entities = [self fetchToBeSendDataEntitiesAndUpdateWithSendStatus];
if (entities.count >= PhobosMaxSendCount) { //大于100条 要对数据进行拆分
//拆分数组
NSArray *array = [GMPhobosTool splitArray:entities withSubSize:PhobosShardCount];
for (NSArray *sub in array) {
[self sendModelArray:sub];
}
} else {
[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 message_item_id = '%@'", model.message_item_id];
bool status = [_squlitManager gm_deleteTable:model.table_name whereFormat:whereStr];
NSLog(@"发送数据成功-删除状态:%d", status);
}
}
#pragma mark - 上报数据失败
- (void)sendError:(NSArray<GMPhobosSqulitModel*> *)entities {
for (GMPhobosSqulitModel *model in entities) {
NSString *whereStr = [NSString stringWithFormat:@"where message_item_id = '%@'", model.message_item_id];
bool status = [_squlitManager gm_updateTable:model.table_name
dicOrModel: @{@"status":@(PhobosDataSendStatus_error)}
whereFormat:whereStr];
NSLog(@"发送失败后-修改状态:%d",status);
}
}
@end