Skip to content

Commit 6f4361d

Browse files
committed
Added initDone to prevent double initializations
* Without this the session and outcomeEvents controllers could be created more than once. * Removed self check in public init method, not needed since it is static - This moved a large nested block a tab back * Split the notificationBlocks:: selector OneSignalHelper into two selectors * Corrected outcome cache clearing tests to restart the app * Other small misc clean up
1 parent 8cf0868 commit 6f4361d

File tree

8 files changed

+124
-110
lines changed

8 files changed

+124
-110
lines changed

iOS_SDK/OneSignalSDK/Source/OneSignal.m

Lines changed: 90 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ @implementation OneSignal
174174
// method can be called the moment the user provides privacy consent.
175175
DelayedInitializationParameters *delayedInitParameters;
176176

177+
// Ensure we only initlize the SDK once even if the public method is called more.
178+
static BOOL initDone;
179+
177180
//used to ensure registration occurs even if APNS does not respond
178181
static NSDate *initializationTime;
179182
static NSTimeInterval maxApnsWait = APNS_TIMEOUT;
@@ -404,6 +407,7 @@ + (void)setDelayIntervals:(NSTimeInterval)apnsMaxWait withRegistrationDelay:(NST
404407
}
405408

406409
+ (void)clearStatics {
410+
initDone = false;
407411
usesAutoPrompt = false;
408412
requestedProvisionalAuthorization = false;
409413

@@ -496,18 +500,8 @@ + (id)initWithLaunchOptions:(NSDictionary*)launchOptions
496500

497501
[self onesignal_Log:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"Called init with app ID: %@", appId]];
498502

499-
initializationTime = [NSDate date];
500-
501-
[OneSignalCacheCleaner cleanCachedUserData];
502-
503-
// Outcomes init
504-
_sessionManager = [[OneSignalSessionManager alloc] init:self];
505-
_outcomeEventsController = [[OneSignalOutcomeEventsController alloc] init:self.sessionManager];
506-
507-
// Some wrapper SDK's call init multiple times and pass nil/NSNull as the appId on the first call
508-
// the app ID is required to download parameters, so do not download params until the appID is provided
509-
if (!didCallDownloadParameters && appId != nil && appId != (id)[NSNull null])
510-
[self downloadIOSParamsWithAppId:appId];
503+
[OneSignalHelper setNotificationActionBlock:actionCallback];
504+
[OneSignalHelper setNotificationReceivedBlock:receivedCallback];
511505

512506
if ([self requiresUserPrivacyConsent]) {
513507
delayedInitializationForPrivacyConsent = true;
@@ -520,83 +514,96 @@ + (id)initWithLaunchOptions:(NSDictionary*)launchOptions
520514
return self;
521515
}
522516

517+
[OneSignalCacheCleaner cleanCachedUserData];
518+
523519
let success = [self initAppId:appId withSettings:settings];
524520
if (!success)
525521
return self;
526522

523+
if (initDone)
524+
return self;
525+
initDone = true;
526+
527+
initializationTime = [NSDate date];
528+
529+
// Outcomes init
530+
_sessionManager = [[OneSignalSessionManager alloc] init:self];
531+
_outcomeEventsController = [[OneSignalOutcomeEventsController alloc] init:self.sessionManager];
532+
533+
// Some wrapper SDK's call init multiple times and pass nil/NSNull as the appId on the first call
534+
// the app ID is required to download parameters, so do not download params until the appID is provided
535+
if (!didCallDownloadParameters && appId != nil && appId != (id)[NSNull null])
536+
[self downloadIOSParamsWithAppId:appId];
537+
527538
if (appId && mShareLocation)
528539
[OneSignalLocation getLocation:false];
529540

530541
let standardUserDefaults = OneSignalUserDefaults.initStandard;
531-
if (self) {
532-
[OneSignal checkIfApplicationImplementsDeprecatedMethods];
533-
534-
[OneSignalHelper notificationBlocks: receivedCallback : actionCallback];
535-
536-
if ([OneSignalHelper isIOSVersionGreaterThanOrEqual:@"8.0"])
537-
registeredWithApple = self.currentPermissionState.accepted;
538-
else
539-
registeredWithApple = self.currentSubscriptionState.pushToken || [standardUserDefaults getSavedBoolForKey:REGISTERED_WITH_APPLE defaultValue:false];
540-
541-
// Check if disabled in-app launch url if passed a NO
542-
if (settings[kOSSettingsKeyInAppLaunchURL] && [settings[kOSSettingsKeyInAppLaunchURL] isKindOfClass:[NSNumber class]])
543-
[self enableInAppLaunchURL:[settings[kOSSettingsKeyInAppLaunchURL] boolValue]];
544-
else if (![standardUserDefaults keyExists:INAPP_LAUNCH_URL]) {
545-
// Only need to default to true if the app doesn't already have this setting saved in NSUserDefaults
546-
[self enableInAppLaunchURL:true];
547-
}
548-
549-
if (settings[kOSSSettingsKeyPromptBeforeOpeningPushURL] && [settings[kOSSSettingsKeyPromptBeforeOpeningPushURL] isKindOfClass:[NSNumber class]]) {
550-
promptBeforeOpeningPushURLs = [settings[kOSSSettingsKeyPromptBeforeOpeningPushURL] boolValue];
551-
[standardUserDefaults saveBoolForKey:PROMPT_BEFORE_OPENING_PUSH_URL withValue:promptBeforeOpeningPushURLs];
552-
}
553-
else
554-
promptBeforeOpeningPushURLs = [standardUserDefaults getSavedBoolForKey:PROMPT_BEFORE_OPENING_PUSH_URL defaultValue:false];
555-
556-
usesAutoPrompt = YES;
557-
if (settings[kOSSettingsKeyAutoPrompt] && [settings[kOSSettingsKeyAutoPrompt] isKindOfClass:[NSNumber class]])
558-
usesAutoPrompt = [settings[kOSSettingsKeyAutoPrompt] boolValue];
559-
560-
if (settings[kOSSettingsKeyProvidesAppNotificationSettings] && [settings[kOSSettingsKeyProvidesAppNotificationSettings] isKindOfClass:[NSNumber class]] && [OneSignalHelper isIOSVersionGreaterThanOrEqual:@"12.0"])
561-
providesAppNotificationSettings = [settings[kOSSettingsKeyProvidesAppNotificationSettings] boolValue];
562-
563-
// Register with Apple's APNS server if we registed once before or if auto-prompt hasn't been disabled.
564-
if (usesAutoPrompt || registeredWithApple)
565-
[self registerForPushNotifications];
566-
else {
567-
[self checkProvisionalAuthorizationStatus];
568-
[self registerForAPNsToken];
569-
}
542+
[OneSignal checkIfApplicationImplementsDeprecatedMethods];
543+
544+
if ([OneSignalHelper isIOSVersionGreaterThanOrEqual:@"8.0"])
545+
registeredWithApple = self.currentPermissionState.accepted;
546+
else
547+
registeredWithApple = self.currentSubscriptionState.pushToken || [standardUserDefaults getSavedBoolForKey:REGISTERED_WITH_APPLE defaultValue:false];
548+
549+
// Check if disabled in-app launch url if passed a NO
550+
if (settings[kOSSettingsKeyInAppLaunchURL] && [settings[kOSSettingsKeyInAppLaunchURL] isKindOfClass:[NSNumber class]])
551+
[self enableInAppLaunchURL:[settings[kOSSettingsKeyInAppLaunchURL] boolValue]];
552+
else if (![standardUserDefaults keyExists:INAPP_LAUNCH_URL]) {
553+
// Only need to default to true if the app doesn't already have this setting saved in NSUserDefaults
554+
[self enableInAppLaunchURL:true];
555+
}
556+
557+
if (settings[kOSSSettingsKeyPromptBeforeOpeningPushURL] && [settings[kOSSSettingsKeyPromptBeforeOpeningPushURL] isKindOfClass:[NSNumber class]]) {
558+
promptBeforeOpeningPushURLs = [settings[kOSSSettingsKeyPromptBeforeOpeningPushURL] boolValue];
559+
[standardUserDefaults saveBoolForKey:PROMPT_BEFORE_OPENING_PUSH_URL withValue:promptBeforeOpeningPushURLs];
560+
}
561+
else
562+
promptBeforeOpeningPushURLs = [standardUserDefaults getSavedBoolForKey:PROMPT_BEFORE_OPENING_PUSH_URL defaultValue:false];
563+
564+
usesAutoPrompt = YES;
565+
if (settings[kOSSettingsKeyAutoPrompt] && [settings[kOSSettingsKeyAutoPrompt] isKindOfClass:[NSNumber class]])
566+
usesAutoPrompt = [settings[kOSSettingsKeyAutoPrompt] boolValue];
567+
568+
if (settings[kOSSettingsKeyProvidesAppNotificationSettings] && [settings[kOSSettingsKeyProvidesAppNotificationSettings] isKindOfClass:[NSNumber class]] && [OneSignalHelper isIOSVersionGreaterThanOrEqual:@"12.0"])
569+
providesAppNotificationSettings = [settings[kOSSettingsKeyProvidesAppNotificationSettings] boolValue];
570+
571+
// Register with Apple's APNS server if we registed once before or if auto-prompt hasn't been disabled.
572+
if (usesAutoPrompt || registeredWithApple)
573+
[self registerForPushNotifications];
574+
else {
575+
[self checkProvisionalAuthorizationStatus];
576+
[self registerForAPNsToken];
577+
}
570578

571-
/* Check if in-app setting passed assigned
572-
* LOGIC: Default - InAppAlerts enabled / InFocusDisplayOption InAppAlert.
573-
* Priority for kOSSettingsKeyInFocusDisplayOption.
574-
*/
575-
NSNumber *IAASetting = settings[kOSSettingsKeyInAppAlerts];
576-
let inAppAlertsPassed = IAASetting && (IAASetting.integerValue == 0 || IAASetting.integerValue == 1);
577-
578-
NSNumber *IFDSetting = settings[kOSSettingsKeyInFocusDisplayOption];
579-
let inFocusDisplayPassed = IFDSetting && IFDSetting.integerValue > -1 && IFDSetting.integerValue < 3;
580-
581-
if (inAppAlertsPassed || inFocusDisplayPassed) {
582-
if (!inFocusDisplayPassed)
583-
self.inFocusDisplayType = (OSNotificationDisplayType)IAASetting.integerValue;
584-
else
585-
self.inFocusDisplayType = (OSNotificationDisplayType)IFDSetting.integerValue;
586-
}
587-
588-
if (self.currentSubscriptionState.userId)
589-
[self registerUser];
590-
else {
591-
[self.osNotificationSettings getNotificationPermissionState:^(OSPermissionState *state) {
592-
593-
if (state.answeredPrompt) {
594-
[self registerUser];
595-
} else {
596-
[self registerUserAfterDelay];
597-
}
598-
}];
599-
}
579+
/* Check if in-app setting passed assigned
580+
* LOGIC: Default - InAppAlerts enabled / InFocusDisplayOption InAppAlert.
581+
* Priority for kOSSettingsKeyInFocusDisplayOption.
582+
*/
583+
NSNumber *IAASetting = settings[kOSSettingsKeyInAppAlerts];
584+
let inAppAlertsPassed = IAASetting && (IAASetting.integerValue == 0 || IAASetting.integerValue == 1);
585+
586+
NSNumber *IFDSetting = settings[kOSSettingsKeyInFocusDisplayOption];
587+
let inFocusDisplayPassed = IFDSetting && IFDSetting.integerValue > -1 && IFDSetting.integerValue < 3;
588+
589+
if (inAppAlertsPassed || inFocusDisplayPassed) {
590+
if (!inFocusDisplayPassed)
591+
self.inFocusDisplayType = (OSNotificationDisplayType)IAASetting.integerValue;
592+
else
593+
self.inFocusDisplayType = (OSNotificationDisplayType)IFDSetting.integerValue;
594+
}
595+
596+
if (self.currentSubscriptionState.userId)
597+
[self registerUser];
598+
else {
599+
[self.osNotificationSettings getNotificationPermissionState:^(OSPermissionState *state) {
600+
601+
if (state.answeredPrompt) {
602+
[self registerUser];
603+
} else {
604+
[self registerUserAfterDelay];
605+
}
606+
}];
600607
}
601608

602609
/*
@@ -614,17 +621,9 @@ + (id)initWithLaunchOptions:(NSDictionary*)launchOptions
614621
[self clearBadgeCount:false];
615622

616623
if (!trackIAPPurchase && [OneSignalTrackIAP canTrack])
617-
trackIAPPurchase = [[OneSignalTrackIAP alloc] init];
618-
619-
if (NSClassFromString(@"UNUserNotificationCenter"))
620-
[OneSignalHelper clearCachedMedia];
624+
trackIAPPurchase = [OneSignalTrackIAP new];
621625

622-
/*
623-
* Downloads params file to see:
624-
* (A) if firebase analytics should be tracked
625-
* (B) if this app requires email authentication
626-
*/
627-
if ([OneSignalTrackFirebaseAnalytics needsRemoteParams])
626+
if ([OneSignalTrackFirebaseAnalytics libraryExists])
628627
[OneSignalTrackFirebaseAnalytics init];
629628

630629
return self;
@@ -664,6 +663,7 @@ + (bool)initAppId:(NSString*)appId withSettings:(NSDictionary*)settings {
664663
// Handle changes to the app id, this might happen on a developer's device when testing
665664
// Will also run the first time OneSignal is initialized
666665
if (app_id && ![app_id isEqualToString:prevAppId]) {
666+
initDone = false;
667667
let sharedUserDefaults = OneSignalUserDefaults.initShared;
668668

669669
// Save app_id to both standard and shared NSUserDefaults

iOS_SDK/OneSignalSDK/Source/OneSignalCacheCleaner.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@
3030
#import "OneSignalCommonDefines.h"
3131
#import "OSUniqueOutcomeNotification.h"
3232
#import "OneSignalUserDefaults.h"
33+
#import "OneSignalHelper.h"
3334

3435
@implementation OneSignalCacheCleaner
3536

3637
+ (void)cleanCachedUserData {
37-
// TODO: Add any other intentional clean up for cached data that might become bulky over time
38-
3938
[self cleanUniqueOutcomeNotifications];
39+
[OneSignalHelper clearCachedMedia];
4040
}
4141

4242
/*

iOS_SDK/OneSignalSDK/Source/OneSignalHelper.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@
4040
// - Notification Opened
4141
+ (NSMutableDictionary*) formatApsPayloadIntoStandard:(NSDictionary*)remoteUserInfo identifier:(NSString*)identifier;
4242
+ (void)lastMessageReceived:(NSDictionary*)message;
43-
+ (void)notificationBlocks:(OSHandleNotificationReceivedBlock)receivedBlock :(OSHandleNotificationActionBlock)actionBlock;
43+
44+
+(void)setNotificationActionBlock:(OSHandleNotificationActionBlock)block;
45+
+(void)setNotificationReceivedBlock:(OSHandleNotificationReceivedBlock)block;
46+
4447
+ (void)handleNotificationReceived:(OSNotificationDisplayType)displayType;
4548
+ (void)handleNotificationReceived:(OSNotificationDisplayType)displayType fromBackground:(BOOL)background;
4649
+ (void)handleNotificationAction:(OSNotificationActionType)actionType actionID:(NSString*)actionID displayType:(OSNotificationDisplayType)displayType;

iOS_SDK/OneSignalSDK/Source/OneSignalHelper.m

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,12 @@ + (void)lastMessageReceived:(NSDictionary*)message {
322322
lastMessageReceived = message;
323323
}
324324

325-
+ (void)notificationBlocks:(OSHandleNotificationReceivedBlock)receivedBlock :(OSHandleNotificationActionBlock)actionBlock {
326-
handleNotificationReceived = receivedBlock;
327-
handleNotificationAction = actionBlock;
325+
+(void)setNotificationActionBlock:(OSHandleNotificationActionBlock)block {
326+
handleNotificationAction = block;
327+
}
328+
329+
+(void)setNotificationReceivedBlock:(OSHandleNotificationReceivedBlock)block {
330+
handleNotificationReceived = block;
328331
}
329332

330333
+ (NSString*)getAppName {
@@ -850,8 +853,12 @@ + (NSString*)downloadMediaAndSaveInBundle:(NSString*)urlString {
850853

851854
}
852855

856+
// TODO: Add back after testing
853857
+(void)clearCachedMedia {
854858
/*
859+
if (!NSClassFromString(@"UNUserNotificationCenter"))
860+
return;
861+
855862
NSArray* cachedFiles = [[NSUserDefaults standardUserDefaults] objectForKey:@"CACHED_MEDIA"];
856863
if (cachedFiles) {
857864
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);

iOS_SDK/OneSignalSDK/Source/OneSignalTrackFirebaseAnalytics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#import "OneSignal.h"
3131

3232
@interface OneSignalTrackFirebaseAnalytics : NSObject
33-
+(BOOL)needsRemoteParams;
33+
+(BOOL)libraryExists;
3434
+(void)init;
3535
+(void)updateFromDownloadParams:(NSDictionary*)params;
3636

iOS_SDK/OneSignalSDK/Source/OneSignalTrackFirebaseAnalytics.m

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ @implementation OneSignalTrackFirebaseAnalytics
3636
static NSTimeInterval lastOpenedTime = 0;
3737
static var trackingEnabled = false;
3838

39-
// Only need to download remote params if app includes Firebase analytics
40-
+ (BOOL)needsRemoteParams {
39+
+ (BOOL)libraryExists {
4140
return NSClassFromString(@"FIRAnalytics") != nil;
4241
}
4342

iOS_SDK/OneSignalSDK/UnitTests/OutcomeIntegrationTests.m

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ - (void)testAttributedIndirectSession_cachedUniqueOutcomeNotificationsCleanedAft
676676
[UnitTestCommonMethods foregroundApp];
677677
[UnitTestCommonMethods initOneSignalAndThreadWait];
678678

679-
// 5. Validate new session is ATTRIBUTED (DIRECT or INDIRECT) and send 2 of the same unique outcomes
679+
// 5. Validate new session is INDIRECT and send 2 of the same unique outcomes
680680
XCTAssertEqual(OneSignal.sessionManager.getSession, INDIRECT);
681681
[OneSignal sendUniqueOutcome:@"unique"];
682682
[OneSignal sendUniqueOutcome:@"unique"];
@@ -692,23 +692,25 @@ - (void)testAttributedIndirectSession_cachedUniqueOutcomeNotificationsCleanedAft
692692
// 7. Close the app again, but for a week to clean out all outdated unique outcome notifications
693693
[UnitTestCommonMethods backgroundApp];
694694
[NSDateOverrider advanceSystemTimeBy:7 * 1441 * 60];
695+
[UnitTestCommonMethods runBackgroundThreads];
696+
[UnitTestCommonMethods clearStateForAppRestart:self];
695697

696698
// 8. Receive 3 more notifications
697699
[UnitTestCommonMethods receiveNotification:@"test_notification_1" wasOpened:NO];
698700
[UnitTestCommonMethods receiveNotification:@"test_notification_2" wasOpened:NO];
699701
[UnitTestCommonMethods receiveNotification:@"test_notification_3" wasOpened:NO];
700702

701703
// 9. Open app again
702-
[UnitTestCommonMethods foregroundApp];
703704
[UnitTestCommonMethods initOneSignalAndThreadWait];
705+
[UnitTestCommonMethods foregroundApp];
704706

705-
// 10. Validate new session is ATTRIBUTED (DIRECT or INDIRECT) and send the same 2 unique outcomes
707+
// 10. Validate new session is INDIRECT and send the same 2 unique outcomes
706708
XCTAssertEqual(OneSignal.sessionManager.getSession, INDIRECT);
707709
[OneSignal sendUniqueOutcome:@"unique"];
708710
[OneSignal sendUniqueOutcome:@"unique"];
709711

710712
// 11. Make sure 2 measure requests have been made in total
711-
[RestClientAsserts assertMeasureAtIndex:5 payload:@{
713+
[RestClientAsserts assertMeasureAtIndex:6 payload:@{
712714
@"direct" : @(false),
713715
@"notification_ids" : @[@"test_notification_1", @"test_notification_2", @"test_notification_3"],
714716
@"id" : @"unique"
@@ -749,21 +751,24 @@ - (void)testAttributedDirectSession_cachedUniqueOutcomeNotificationsCleanedAfter
749751
// 7. Close the app again, but for a week to clean out all outdated unique outcome notifications
750752
[UnitTestCommonMethods backgroundApp];
751753
[NSDateOverrider advanceSystemTimeBy:7 * 1441 * 60];
754+
[UnitTestCommonMethods runBackgroundThreads];
755+
[UnitTestCommonMethods clearStateForAppRestart:self];
756+
757+
// 8. Open app again
758+
[UnitTestCommonMethods initOneSignalAndThreadWait];
759+
[UnitTestCommonMethods backgroundApp];
752760

753-
// 8. Receive 1 more notification and open it
761+
// 9. Receive 1 more notification and open it
754762
[UnitTestCommonMethods receiveNotification:@"test_notification_2" wasOpened:YES];
755-
756-
// 9. Open app again
757763
[UnitTestCommonMethods foregroundApp];
758-
[UnitTestCommonMethods initOneSignalAndThreadWait];
759764

760-
// 10. Validate new session is ATTRIBUTED (DIRECT or INDIRECT) and send the same 2 unique outcomes
765+
// 10. Validate new session is DIRECT and send the same 2 unique outcomes
761766
XCTAssertEqual(OneSignal.sessionManager.getSession, DIRECT);
762767
[OneSignal sendUniqueOutcome:@"unique"];
763768
[OneSignal sendUniqueOutcome:@"unique"];
764769

765770
// 11. Make sure 2 measure requests have been made in total
766-
[RestClientAsserts assertMeasureAtIndex:6 payload:@{
771+
[RestClientAsserts assertMeasureAtIndex:8 payload:@{
767772
@"direct" : @(true),
768773
@"notification_ids" : @[@"test_notification_2"],
769774
@"id" : @"unique"

iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalTrackFirebaseAnalyticsOverrider.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ +(void)load {
5353
[self reset];
5454

5555
injectStaticSelector([OneSignalTrackFirebaseAnalyticsOverrider class], @selector(overrideLogEventWithName:parameters:), [OneSignalTrackFirebaseAnalytics class], @selector(logEventWithName:parameters:));
56-
injectStaticSelector([OneSignalTrackFirebaseAnalyticsOverrider class], @selector(overrideNeedsRemoteParams), [OneSignalTrackFirebaseAnalytics class], @selector(needsRemoteParams));
56+
injectStaticSelector([OneSignalTrackFirebaseAnalyticsOverrider class], @selector(overrideNeedsRemoteParams), [OneSignalTrackFirebaseAnalytics class], @selector(libraryExists));
5757
}
5858

5959
+(void)overrideLogEventWithName:(NSString*)name parameters:(NSDictionary*)params {

0 commit comments

Comments
 (0)