Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
GMPhobos
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gengmeiios
GMPhobos
Commits
2d57d66e
Commit
2d57d66e
authored
5 years ago
by
井庆林
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
优化
parent
19039216
master
ajp/dev
houchaoxin/dev
jql/phobos
jql/test
jz/master
lwq/3.38.1
lwq/7.40.1_phobos
lwq_7.40.1_phobos
lwq_7.40.1_phpbos
lym/phobos
revert-b8f58e72
rmc/changeSendNow
wxd_gmphobos
zx/refererLinkFix
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.13
3.0.12
3.0.11
3.0.10
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
1 merge request
!67
Lym/phobos
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
164 additions
and
112 deletions
+164
-112
GMViewController.m
Example/GMPhobos/GMViewController.m
+13
-9
NewPhobos.m
GMPhobos/Classes/NewPhobos.m
+20
-14
Phobos.m
GMPhobos/Classes/Phobos.m
+2
-2
PhobosDataManager.h
GMPhobos/Classes/PhobosDataManager.h
+10
-13
PhobosDataManager.m
GMPhobos/Classes/PhobosDataManager.m
+119
-74
No files found.
Example/GMPhobos/GMViewController.m
View file @
2d57d66e
...
...
@@ -66,15 +66,19 @@ NSString *const MockCityId = @"beijing";
// [Phobos track:@"page_view" attributes:dict];
// array = [GMCache fetchObjectAtDocumentPathWithkey:PhobosCacheKey];
for
(
int
i
=
0
;
i
<
200
;
i
++
)
{
[
Phobos
track
:[
NSString
stringWithFormat
:
@"tt-%d"
,
i
]
attributes
:
dict
sendNow
:
YES
];
[
Phobos
track
:[
NSString
stringWithFormat
:
@"pv-%d"
,
i
]
attributes
:
dict
sendNow
:
(
arc4random
()
%
2
==
0
)];
}
for
(
int
i
=
5
;
i
<
5
;
i
++
)
{
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++) {
// [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
{
...
...
This diff is collapsed.
Click to expand it.
GMPhobos/Classes/NewPhobos.m
View file @
2d57d66e
...
...
@@ -32,8 +32,6 @@ static NewPhobos *_sharedClient;
@implementation
NewPhobos
static
dispatch_semaphore_t
_phobos_semaphore
;
+
(
NewPhobos
*
)
clientWithAppName
:(
NSString
*
)
appName
channelId
:(
NSString
*
)
channelId
{
NewPhobos
.
sharedClient
.
appName
=
appName
;
NewPhobos
.
sharedClient
.
channelId
=
channelId
;
...
...
@@ -42,7 +40,6 @@ static dispatch_semaphore_t _phobos_semaphore;
-
(
instancetype
)
init
{
if
(
self
=
[
super
init
])
{
_phobos_semaphore
=
dispatch_semaphore_create
(
1
);
_appName
=
@""
;
_channelId
=
@""
;
_logEnabled
=
NO
;
...
...
@@ -218,7 +215,7 @@ static dispatch_semaphore_t _phobos_semaphore;
@"uuid"
:
[
PhobosUtil
deviceId
],
@"build_version_release"
:
[[
UIDevice
currentDevice
]
systemVersion
],
};
[
NewPhobos
track
:
@"on_app_session_over"
a
ttributes
:
dict
];
[
NewPhobos
track
SessionOverWithA
ttributes
:
dict
];
[
GMCache
removeObjectAtDocumentPathWithkey
:
PhobosBeginTime
];
//当前session结束之后,把id置为0
_serialId
=
0
;
...
...
@@ -328,7 +325,6 @@ static dispatch_semaphore_t _phobos_semaphore;
[
deviceParams
setValue
:[
PhobosUtil
getIPAddress
:
YES
]
forKey
:
@"ip"
];
[
deviceParams
setValue
:
PhobosSafeString
(
_networkStatus
)
forKey
:
@"net_type"
];
[
deviceParams
setValue
:
PhobosSafeString
([
PhobosUtil
platform
])
forKey
:
@"model"
];
[
deviceParams
setValue
:
@
(
_isGray
)
forKey
:
@"isGray"
];
[
deviceParams
setValue
:
PhobosSafeString
([
UIDevice
currentDevice
].
systemVersion
)
forKey
:
@"sys_version"
];
NSMutableDictionary
*
appParams
=
[
NSMutableDictionary
new
];
...
...
@@ -337,6 +333,7 @@ static dispatch_semaphore_t _phobos_semaphore;
[
appParams
setValue
:
PhobosSafeString
(
_appVersion
)
forKey
:
@"version"
];
[
appParams
setValue
:
PhobosSafeString
(
_channelId
)
forKey
:
@"channel"
];
[
appParams
setValue
:
PhobosSafeString
(
_userType
)
forKey
:
@"user_type"
];
[
appParams
setValue
:
@
(
_isGray
)
forKey
:
@"is_gray"
];
[
appParams
setValue
:
PhobosSafeString
(
_currentCityId
)
forKey
:
@"current_city_id"
];
[
appParams
setValue
:
@
(
_serialId
++
)
forKey
:
@"serial_id"
];
...
...
@@ -381,11 +378,11 @@ static dispatch_semaphore_t _phobos_semaphore;
}
+
(
void
)
onClickButtonWithAttributes
:
(
NSDictionary
*
)
attributes
{
[
self
track
:
@"on_cick_button"
attributes
:
attributes
];
[
self
track
:
@"on_c
l
ick_button"
attributes
:
attributes
];
}
+
(
void
)
onClickButtonWithAttributes
:
(
NSDictionary
*
)
attributes
sendNow
:
(
BOOL
)
sendNow
{
[
self
track
:
@"on_cick_button"
attributes
:
attributes
sendNow
:
sendNow
];
[
self
track
:
@"on_c
l
ick_button"
attributes
:
attributes
sendNow
:
sendNow
];
}
+
(
void
)
track
:
(
NSString
*
)
eventName
{
...
...
@@ -412,25 +409,34 @@ static dispatch_semaphore_t _phobos_semaphore;
NSDictionary
*
dataDict
=
[
_sharedClient
prepareDictionaryForEvent
:
eventName
attributes
:
attributes
];
@try
{
NSData
*
JSON
=
[
PhobosUtil
encodeJSON
:
dataDict
];
[
PhobosDataManager
insertData
:
dataDict
sendAPI
:
currentAPI
];
[
self
disposeSendDataWithImmediately
:
sendNow
];
[
PhobosDataManager
insertData
:
dataDict
sendAPI
:
currentAPI
completion
:^
(
BOOL
contextDidSave
,
NSError
*
_Nullable
error
)
{
[
self
disposeSendDataWithImmediately
:
sendNow
];
}];
}
@catch
(
NSException
*
exception
)
{
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
{
NSInteger
count
=
[
PhobosDataManager
fetchCountOfToBeSendEntities
];
if
(
immediately
||
count
>=
PhobosShardCount
)
{
dispatch_semaphore_wait
(
_phobos_semaphore
,
DISPATCH_TIME_FOREVER
);
NSArray
<
PhobosSendDataEntity
*>
*
entities
=
[
PhobosDataManager
fetchToBeSendDataEntities
];
[
PhobosDataManager
updateDataEntities
:
entities
sendStatus
:
PhobosDataSendStatusSending
];
dispatch_semaphore_signal
(
_phobos_semaphore
);
NSArray
<
PhobosSendDataEntity
*>
*
entities
=
[
PhobosDataManager
fetchToBeSendDataEntitiesAndUpdateWithSendStatus
:
PhobosDataSendStatusSending
];
[
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
];
}];
}
}
...
...
This diff is collapsed.
Click to expand it.
GMPhobos/Classes/Phobos.m
View file @
2d57d66e
...
...
@@ -65,7 +65,7 @@ static BOOL isGray = NO;
if
(
isGray
)
{
[
NewPhobos
onClickButtonWithAttributes
:
attributes
];
}
else
{
[
self
track
:
@"on_cick_button"
attributes
:
attributes
];
[
self
track
:
@"on_c
l
ick_button"
attributes
:
attributes
];
}
}
...
...
@@ -73,7 +73,7 @@ static BOOL isGray = NO;
if
(
isGray
)
{
[
NewPhobos
onClickButtonWithAttributes
:
attributes
sendNow
:
sendNow
];
}
else
{
[
self
track
:
@"on_cick_button"
attributes
:
attributes
sendNow
:
sendNow
];
[
self
track
:
@"on_c
l
ick_button"
attributes
:
attributes
sendNow
:
sendNow
];
}
}
...
...
This diff is collapsed.
Click to expand it.
GMPhobos/Classes/PhobosDataManager.h
View file @
2d57d66e
...
...
@@ -20,23 +20,22 @@ typedef NS_ENUM(NSInteger, PhobosDataSendStatus) {
@interface
PhobosDataManager
:
NSObject
/** 获取待发送数据,包含待发送数据和发送失败数据 */
+
(
NSArray
<
PhobosSendDataEntity
*>
*
)
fetchToBeSendDataEntities
;
/**
*
通过 searchFilter 获取数据
*
获取待发送和发送失败的数据数量
*/
+
(
NS
Array
<
PhobosSendDataEntity
*>
*
)
fetchDataEntitiesWithPredicate
:(
NSPredicate
*
)
searchFilter
;
+
(
NS
UInteger
)
fetchCountOfToBeSendEntities
;
/**
* 获取待发送和发送失败的数据数量
* 获取待发送数据,包含待发送数据和发送失败数据
* predicate 通过谓词获取相应的数据
*/
+
(
NSUInteger
)
fetchCountOfToBeSendEntities
;
+
(
NSArray
<
PhobosSendDataEntity
*>
*
)
fetchToBeSendDataEntities
;
+
(
NSArray
<
PhobosSendDataEntity
*>
*
)
fetchDataEntitiesWithPredicate
:(
NSPredicate
*
)
predicate
;
/**
*
通过 searchFilter 获取数据数量
*
获取待发送数据,包含待发送数据和发送失败数据, 并修改状态为sendStatus
*/
+
(
NS
UInteger
)
fetchCountOfEntitiesWithPredicate
:(
NSPredicate
*
)
searchFilter
;
+
(
NS
Array
<
PhobosSendDataEntity
*>
*
)
fetchToBeSendDataEntitiesAndUpdateWithSendStatus
:(
PhobosDataSendStatus
)
sendStatus
;
/**
* 插入埋点数据
...
...
@@ -45,7 +44,6 @@ typedef NS_ENUM(NSInteger, PhobosDataSendStatus) {
* completion 插入数据库成功后的回调方法,在保存完成后调用的完成块。如果发生错误,块将以“BOOL”和“NSError”实例的形式传递成功状态。总是在主队列上调用。
* 该方法调用完成,fetch方法获取相应的数据就可获取到,不需要等completion回调。
*/
+
(
void
)
insertData
:(
NSDictionary
*
)
data
sendAPI
:(
NSString
*
)
sendAPI
;
+
(
void
)
insertData
:(
NSDictionary
*
)
data
sendAPI
:(
NSString
*
)
sendAPI
completion
:(
MRSaveCompletionHandler
)
completion
;
/**
...
...
@@ -55,13 +53,12 @@ typedef NS_ENUM(NSInteger, PhobosDataSendStatus) {
* completion 插入数据库成功后的回调方法,在保存完成后调用的完成块。如果发生错误,块将以“BOOL”和“NSError”实例的形式传递成功状态。总是在主队列上调用。
* 该方法调用完成,fetch方法获取相应的数据就可获取到,不需要等completion回调。
*/
+
(
void
)
updateDataEntities
:(
NSArray
<
PhobosSendDataEntity
*>
*
)
entities
sendStatus
:(
PhobosDataSendStatus
)
sendStatus
;
+
(
void
)
updateDataEntities
:(
NSArray
<
PhobosSendDataEntity
*>
*
)
entities
sendStatus
:(
PhobosDataSendStatus
)
sendStatus
completion
:(
MRSaveCompletionHandler
)
completion
;
/**
* 删除数据
* 删除所有数据
* 仅限单元测试使用
*/
+
(
void
)
deleteDataEntities
:(
NSArray
<
PhobosSendDataEntity
*>
*
)
entities
;
+
(
void
)
deleteAllEntities
;
@end
...
...
This diff is collapsed.
Click to expand it.
GMPhobos/Classes/PhobosDataManager.m
View file @
2d57d66e
...
...
@@ -15,118 +15,163 @@
@implementation
PhobosDataManager
static
NSManagedObjectContext
*
PhobosDefaultContext
;
static
dispatch_semaphore_t
phobos_semaphore_t
;
static
NSUInteger
PhobosToBeSendEntitiesCount
=
0
;
+
(
void
)
initialize
{
static
dispatch_once_t
onceToken
;
dispatch_once
(
&
onceToken
,
^
{
phobos_semaphore_t
=
dispatch_semaphore_create
(
1
);
// 创建 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
];
[
self
setupSDK
];
[
self
resetData
];
});
}
+
(
NSArray
<
PhobosSendDataEntity
*>
*
)
fetchToBeSendDataEntities
{
NSPredicate
*
predicate
=
[
NSPredicate
predicateWithFormat
:
@"status = %d or status = %d"
,
PhobosDataSendStatusToBeSend
,
PhobosDataSendStatusError
];
return
[
self
fetchDataEntitiesWithPredicate
:
predicate
];
}
+
(
NSArray
<
PhobosSendDataEntity
*>
*
)
fetchDataEntitiesWithPredicate
:
(
NSPredicate
*
)
searchFilter
{
return
[
PhobosSendDataEntity
MR_findAllWithPredicate
:
searchFilter
inContext
:
PhobosDefaultContext
];
+
(
NSUInteger
)
fetchCountOfToBeSendEntities
{
return
PhobosToBeSendEntitiesCount
;
}
+
(
NS
UInteger
)
fetchCountOfToBeSend
Entities
{
+
(
NS
Array
<
PhobosSendDataEntity
*>
*
)
fetchToBeSendData
Entities
{
NSPredicate
*
predicate
=
[
NSPredicate
predicateWithFormat
:
@"status = %d or status = %d"
,
PhobosDataSendStatusToBeSend
,
PhobosDataSendStatusError
];
return
[
self
fetch
CountOf
EntitiesWithPredicate
:
predicate
];
return
[
self
fetch
Data
EntitiesWithPredicate
:
predicate
];
}
+
(
NSUInteger
)
fetchCountOfEntitiesWithPredicate
:
(
NSPredicate
*
)
searchFilter
{
return
[[
PhobosSendDataEntity
MR_numberOfEntitiesWithPredicate
:
searchFilter
inContext
:
PhobosDefaultContext
]
integerValue
];
+
(
NSArray
<
PhobosSendDataEntity
*>
*
)
fetchDataEntitiesWithPredicate
:
(
NSPredicate
*
)
predicate
{
__block
NSArray
*
results
=
nil
;
[[
self
PhobosContext
]
performBlockAndWait
:
^
{
results
=
[
self
noWaitFetchDataEntitiesWithPredicate
:
predicate
];
}];
return
results
;
}
+
(
void
)
insertData
:
(
NSDictionary
*
)
data
sendAPI
:
(
NSString
*
)
sendAPI
{
[
self
insertData
:
data
sendAPI
:
sendAPI
completion
:
nil
];
+
(
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
;
}
dispatch_semaphore_wait
(
phobos_semaphore_t
,
DISPATCH_TIME_FOREVER
);
PhobosSendDataEntity
*
entity
=
[
PhobosSendDataEntity
MR_createEntityInContext
:
PhobosDefaultContext
];
entity
.
data
=
[
data
mj_JSONData
];
entity
.
api
=
sendAPI
;
entity
.
status
=
PhobosDataSendStatusToBeSend
;
entity
.
id
=
mach_absolute_time
();
dispatch_semaphore_signal
(
phobos_semaphore_t
);
[
self
saveWithCompletion
:
completion
];
}
+
(
void
)
updateDataEntities
:
(
NSArray
<
PhobosSendDataEntity
*>
*
)
entities
sendStatus
:
(
PhobosDataSendStatus
)
sendStatus
{
[
self
updateDataEntities
:
entities
sendStatus
:
sendStatus
completion
:
nil
];
[[
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
)
{
dispatch_semaphore_wait
(
phobos_semaphore_t
,
DISPATCH_TIME_FOREVER
);
[
entities
enumerateObjectsUsingBlock
:
^
(
PhobosSendDataEntity
*
obj
,
NSUInteger
idx
,
BOOL
*
_Nonnull
stop
)
{
obj
.
status
=
sendStatus
;
[[
self
PhobosContext
]
performBlockAndWait
:
^
{
[
self
noWaitUpdateEntities
:
entities
sendStatus
:
sendStatus
completion
:
completion
];
}];
dispatch_semaphore_signal
(
phobos_semaphore_t
);
[
self
saveWithCompletion
:
completion
];
}
}
+
(
void
)
deleteDataEntities
:
(
NSArray
<
PhobosSendDataEntity
*>
*
)
entities
{
if
(
entities
.
count
>
0
)
{
dispatch_semaphore_wait
(
phobos_semaphore_t
,
DISPATCH_TIME_FOREVER
);
[
entities
enumerateObjectsUsingBlock
:
^
(
PhobosSendDataEntity
*
obj
,
NSUInteger
idx
,
BOOL
*
_Nonnull
stop
)
{
[
obj
MR_deleteEntityInContext
:
PhobosDefaultContext
];
}];
dispatch_semaphore_signal
(
phobos_semaphore_t
);
+
(
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
;
}
}
+
(
void
)
deleteAllEntities
{
dispatch_semaphore_wait
(
phobos_semaphore_t
,
DISPATCH_TIME_FOREVER
);
[
PhobosSendDataEntity
MR_truncateAllInContext
:
PhobosDefaultContext
];
dispatch_semaphore_signal
(
phobos_semaphore_t
);
[
self
saveWithCompletion
:
nil
];
/**
* 不使用同步线程安全方案[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
{
[
PhobosDefaultContext
MR_saveOnlySelfWithCompletion
:
completion
];
[
[
self
PhobosContext
]
MR_saveOnlySelfWithCompletion
:
completion
];
}
@end
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment