25
25
26
26
const static int64_t kMillisPerDay = 8.64e+7 ;
27
27
28
+ /* * Creates and/or returns a singleton NSString that is the NSCoding file location.
29
+ *
30
+ * @return The NSCoding file path.
31
+ */
32
+ static NSString *ArchivePath () {
33
+ static NSString *archivePath;
34
+ static dispatch_once_t onceToken;
35
+ dispatch_once (&onceToken, ^{
36
+ NSString *cachePath =
37
+ NSSearchPathForDirectoriesInDomains (NSCachesDirectory, NSUserDomainMask, YES )[0 ];
38
+ archivePath = [NSString stringWithFormat: @" %@ /google-sdks-events/GDTCCTPrioritizer" , cachePath];
39
+ });
40
+ return archivePath;
41
+ }
42
+
28
43
@implementation GDTCCTPrioritizer
29
44
30
45
+ (void )load {
@@ -34,6 +49,10 @@ + (void)load {
34
49
[[GDTCORRegistrar sharedInstance ] registerPrioritizer: prioritizer target: kGDTCORTargetCSH ];
35
50
}
36
51
52
+ + (BOOL )supportsSecureCoding {
53
+ return YES ;
54
+ }
55
+
37
56
+ (instancetype )sharedInstance {
38
57
static GDTCCTPrioritizer *sharedInstance;
39
58
static dispatch_once_t onceToken;
@@ -238,9 +257,127 @@ typedef NS_ENUM(NSInteger, GDTCCTQoSTier) {
238
257
}];
239
258
}
240
259
260
+ #pragma mark - NSSecureCoding
261
+
262
+ /* * NSSecureCoding key for the CCTEvents property. */
263
+ static NSString *const GDTCCTUploaderCCTEventsKey = @" GDTCCTUploaderCCTEventsKey" ;
264
+
265
+ /* * NSSecureCoding key for the CCTEvents property. */
266
+ static NSString *const GDTCCTUploaderFLLEventsKey = @" GDTCCTUploaderFLLEventsKey" ;
267
+
268
+ /* * NSSecureCoding key for the CCTEvents property. */
269
+ static NSString *const GDTCCTUploaderCSHEventsKey = @" GDTCCTUploaderCSHEventsKey" ;
270
+
271
+ - (instancetype )initWithCoder : (NSCoder *)coder {
272
+ GDTCCTPrioritizer *sharedInstance = [GDTCCTPrioritizer sharedInstance ];
273
+ if (sharedInstance) {
274
+ NSSet *classes = [NSSet setWithObjects: [NSMutableSet class ], [GDTCOREvent class ], nil ];
275
+ NSMutableSet *decodedCCTEvents = [coder decodeObjectOfClasses: classes
276
+ forKey: GDTCCTUploaderCCTEventsKey];
277
+ if (decodedCCTEvents) {
278
+ sharedInstance->_CCTEvents = decodedCCTEvents;
279
+ }
280
+ NSMutableSet *decodedFLLEvents = [coder decodeObjectOfClasses: classes
281
+ forKey: GDTCCTUploaderFLLEventsKey];
282
+ if (decodedFLLEvents) {
283
+ sharedInstance->_FLLEvents = decodedFLLEvents;
284
+ }
285
+ NSMutableSet *decodedCSHEvents = [coder decodeObjectOfClasses: classes
286
+ forKey: GDTCCTUploaderCSHEventsKey];
287
+ if (decodedCSHEvents) {
288
+ sharedInstance->_CSHEvents = decodedCSHEvents;
289
+ }
290
+ }
291
+ return sharedInstance;
292
+ }
293
+
294
+ - (void )encodeWithCoder : (NSCoder *)coder {
295
+ GDTCCTPrioritizer *sharedInstance = [GDTCCTPrioritizer sharedInstance ];
296
+ NSMutableSet <GDTCOREvent *> *CCTEvents = sharedInstance->_CCTEvents ;
297
+ if (CCTEvents) {
298
+ [coder encodeObject: CCTEvents forKey: GDTCCTUploaderCCTEventsKey];
299
+ }
300
+ NSMutableSet <GDTCOREvent *> *FLLEvents = sharedInstance->_FLLEvents ;
301
+ if (FLLEvents) {
302
+ [coder encodeObject: FLLEvents forKey: GDTCCTUploaderFLLEventsKey];
303
+ }
304
+ NSMutableSet <GDTCOREvent *> *CSHEvents = sharedInstance->_CSHEvents ;
305
+ if (CSHEvents) {
306
+ [coder encodeObject: CSHEvents forKey: GDTCCTUploaderCSHEventsKey];
307
+ }
308
+ }
309
+
310
+ #pragma mark - GDTCORLifecycleProtocol
311
+
312
+ - (void )appWillForeground : (GDTCORApplication *)app {
313
+ if (@available (macOS 10.13 , iOS 11.0 , tvOS 11.0 , *)) {
314
+ NSError *error;
315
+ NSData *data = [NSData dataWithContentsOfFile: ArchivePath ()];
316
+ if (data) {
317
+ [NSKeyedUnarchiver unarchivedObjectOfClass: [GDTCCTPrioritizer class ]
318
+ fromData: data
319
+ error: &error];
320
+ }
321
+ } else {
322
+ #if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH
323
+ [NSKeyedUnarchiver unarchiveObjectWithFile: ArchivePath ()];
324
+ #endif
325
+ }
326
+ }
327
+
328
+ - (void )appWillBackground : (GDTCORApplication *)app {
329
+ dispatch_async (_queue, ^{
330
+ // Immediately request a background task to run until the end of the current queue of work, and
331
+ // cancel it once the work is done.
332
+ __block GDTCORBackgroundIdentifier bgID =
333
+ [app beginBackgroundTaskWithName: @" GDTStorage"
334
+ expirationHandler: ^{
335
+ [app endBackgroundTask: bgID];
336
+ bgID = GDTCORBackgroundIdentifierInvalid;
337
+ }];
338
+
339
+ if (@available (macOS 10.13 , iOS 11.0 , tvOS 11.0 , *)) {
340
+ NSError *error;
341
+ NSData *data = [NSKeyedArchiver archivedDataWithRootObject: self
342
+ requiringSecureCoding: YES
343
+ error: &error];
344
+ [data writeToFile: ArchivePath () atomically: YES ];
345
+ } else {
346
+ #if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH
347
+ [NSKeyedArchiver archiveRootObject: self toFile: ArchivePath ()];
348
+ #endif
349
+ }
350
+
351
+ // End the background task if it's still valid.
352
+ [app endBackgroundTask: bgID];
353
+ bgID = GDTCORBackgroundIdentifierInvalid;
354
+ });
355
+ }
356
+
357
+ - (void )appWillTerminate : (GDTCORApplication *)application {
358
+ dispatch_sync (_queue, ^{
359
+ if (@available (macOS 10.13 , iOS 11.0 , tvOS 11.0 , *)) {
360
+ NSError *error;
361
+ NSData *data = [NSKeyedArchiver archivedDataWithRootObject: self
362
+ requiringSecureCoding: YES
363
+ error: &error];
364
+ [data writeToFile: ArchivePath () atomically: YES ];
365
+ } else {
366
+ #if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH
367
+ [NSKeyedArchiver archiveRootObject: self toFile: ArchivePath ()];
368
+ #endif
369
+ }
370
+ });
371
+ }
372
+
241
373
#pragma mark - GDTCORUploadPackageProtocol
242
374
243
375
- (void )packageDelivered : (GDTCORUploadPackage *)package successful : (BOOL )successful {
376
+ // If sending the package wasn't successful, we should keep track of these events.
377
+ if (!successful) {
378
+ return ;
379
+ }
380
+
244
381
dispatch_async (_queue, ^{
245
382
NSSet <GDTCOREvent *> *events = [package.events copy ];
246
383
for (GDTCOREvent *event in events) {
0 commit comments