|
25 | 25 | * THE SOFTWARE. |
26 | 26 | */ |
27 | 27 |
|
| 28 | +#import <stdatomic.h> |
28 | 29 | #import "OneSignalFramework.h" |
29 | 30 | #import <OneSignalOSCore/OneSignalOSCore-Swift.h> |
30 | 31 | #import "OneSignalInternal.h" |
@@ -461,22 +462,41 @@ + (void)init { |
461 | 462 | // operations during iOS prewarm (before first unlock) when shared UserDefaults reads |
462 | 463 | // are unreliable. UIApplication isn't available to OneSignalOSCore (which OneSignalConfig |
463 | 464 | // lives in), so the main app injects the check here at initialize time. |
464 | | - OneSignalConfig.isProtectedDataAvailableProvider = ^BOOL { |
465 | | - return UIApplication.sharedApplication.isProtectedDataAvailable; |
466 | | - }; |
467 | | - |
468 | | - // When the device unlocks after a locked-storage launch (iOS app prewarm), drive `start()` |
469 | | - // again. `start()` was gated by the predicate while protected data was unavailable; the |
470 | | - // re-call now sees the gate clear, refreshes the model stores from shared UserDefaults, |
471 | | - // and takes the normal Path 1 cache load. |
472 | | - static dispatch_once_t protectedDataObserverOnce; |
473 | | - dispatch_once(&protectedDataObserverOnce, ^{ |
474 | | - [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationProtectedDataDidBecomeAvailable |
475 | | - object:nil |
476 | | - queue:nil |
477 | | - usingBlock:^(NSNotification * _Nonnull note) { |
| 465 | + // |
| 466 | + // The flag is cached in an atomic BOOL and updated from |
| 467 | + // UIApplicationProtectedData{DidBecomeAvailable,WillBecomeUnavailable} so we never touch |
| 468 | + // `UIApplication` synchronously from the arbitrary threads that hit the predicate. |
| 469 | + static _Atomic(BOOL) gProtectedDataAvailable = NO; |
| 470 | + static dispatch_once_t protectedDataOnce; |
| 471 | + dispatch_once(&protectedDataOnce, ^{ |
| 472 | + // Seed the cache on the main thread once. UIApplication APIs are main-thread-only. |
| 473 | + // On a normal launch this resolves to YES near-immediately; on a prewarm launch |
| 474 | + // before first unlock it stays NO and the notification will flip it later. |
| 475 | + dispatch_async(dispatch_get_main_queue(), ^{ |
| 476 | + atomic_store(&gProtectedDataAvailable, UIApplication.sharedApplication.isProtectedDataAvailable); |
| 477 | + }); |
| 478 | + |
| 479 | + NSNotificationCenter *center = NSNotificationCenter.defaultCenter; |
| 480 | + [center addObserverForName:UIApplicationProtectedDataDidBecomeAvailable |
| 481 | + object:nil |
| 482 | + queue:nil |
| 483 | + usingBlock:^(NSNotification * _Nonnull note) { |
| 484 | + atomic_store(&gProtectedDataAvailable, YES); |
| 485 | + // Drive `start()` again — it was gated by the predicate while protected data was |
| 486 | + // unavailable. The re-call now sees the gate clear, refreshes the model stores |
| 487 | + // from shared UserDefaults, and takes the normal Path 1 cache load. |
478 | 488 | [OneSignalUserManagerImpl.sharedInstance start]; |
479 | 489 | }]; |
| 490 | + [center addObserverForName:UIApplicationProtectedDataWillBecomeUnavailable |
| 491 | + object:nil |
| 492 | + queue:nil |
| 493 | + usingBlock:^(NSNotification * _Nonnull note) { |
| 494 | + atomic_store(&gProtectedDataAvailable, NO); |
| 495 | + }]; |
| 496 | + |
| 497 | + OneSignalConfig.isProtectedDataAvailableProvider = ^BOOL { |
| 498 | + return atomic_load(&gProtectedDataAvailable); |
| 499 | + }; |
480 | 500 | }); |
481 | 501 |
|
482 | 502 | // TODO: We moved this check to the top of this method, we should test this. |
@@ -570,7 +590,8 @@ + (void)handleAppIdChange:(NSString*)appId { |
570 | 590 | // Drop cached identifiers — a real app-id change invalidates them. |
571 | 591 | [OSResilientStorage setStrings:@{ |
572 | 592 | OSResilientStorage.keySubscriptionId: @"", |
573 | | - OSResilientStorage.keyOneSignalId: @"" |
| 593 | + OSResilientStorage.keyOneSignalId: @"", |
| 594 | + OSResilientStorage.keyReceiveReceiptsEnabled: @"" |
574 | 595 | }]; |
575 | 596 |
|
576 | 597 | // Clear all cached data, does not start User Module nor call logout. |
|
0 commit comments