Skip to content

Commit a4e6920

Browse files
authored
Merge pull request #931 from OneSignal/fix/stopped_iams_still_display
Fixing impressions being sent for in-active IAMs
2 parents a151734 + 95e5c75 commit a4e6920

File tree

7 files changed

+100
-32
lines changed

7 files changed

+100
-32
lines changed

iOS_SDK/OneSignalSDK/Source/OSInAppMessageViewController.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ NS_ASSUME_NONNULL_BEGIN
3939
- (void)messageViewDidSelectAction:(OSInAppMessage *)message withAction:(OSInAppMessageAction *)action;
4040
- (void)messageViewDidDisplayPage:(OSInAppMessage *)message withPageId:(NSString *)pageId;
4141
- (void)messageViewControllerWasDismissed;
42-
- (void)webViewContentFinishedLoading;
42+
- (void)webViewContentFinishedLoading:(OSInAppMessage *)message;
43+
- (void)messageIsNotActive:(OSInAppMessage *)message;
4344

4445
@end
4546

iOS_SDK/OneSignalSDK/Source/OSInAppMessageViewController.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,9 @@ - (void)loadPreviewMessageContent {
266266

267267
- (void)encounteredErrorLoadingMessageContent:(NSError * _Nullable)error {
268268
let message = [NSString stringWithFormat:@"An error occurred while attempting to load message content: %@", error.description ?: @"Unknown Error"];
269+
if (error.code == 410 || error.code == 404) {
270+
[self.delegate messageIsNotActive:self.message];
271+
}
269272
[OneSignal onesignal_Log:ONE_S_LL_ERROR message:message];
270273
}
271274

@@ -649,7 +652,7 @@ - (void)jsEventOccurredWithBody:(NSData *)body {
649652
// The page is fully loaded and should now be displayed
650653
// This is only fired once the javascript on the page sends the "rendering_complete" type event
651654
dispatch_async(dispatch_get_main_queue(), ^{
652-
[self.delegate webViewContentFinishedLoading];
655+
[self.delegate webViewContentFinishedLoading:self.message];
653656
[OneSignalHelper performSelector:@selector(displayMessage) onMainThreadOnObject:self withObject:nil afterDelay:0.0f];
654657
});
655658
break;

iOS_SDK/OneSignalSDK/Source/OSMessagingController.m

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,19 @@ - (void)resetRedisplayMessagesBySession {
187187
}
188188
}
189189

190+
- (void)deleteInactiveMessage:(OSInAppMessage *)message {
191+
let deleteMessage = [NSString stringWithFormat:@"Deleting inactive in-app message from cache: %@", message.messageId];
192+
[OneSignal onesignal_Log:ONE_S_LL_ERROR message:deleteMessage];
193+
NSMutableArray *newMessagesArray = [NSMutableArray arrayWithArray:self.messages];
194+
[newMessagesArray removeObject: message];
195+
self.messages = newMessagesArray;
196+
if (self.messages) {
197+
[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_MESSAGES_ARRAY withValue:self.messages];
198+
} else {
199+
[OneSignalUserDefaults.initStandard removeValueForKey:OS_IAM_MESSAGES_ARRAY];
200+
}
201+
}
202+
190203
/*
191204
Part of redisplay logic
192205
Remove IAMs that the last display time was six month ago
@@ -275,21 +288,28 @@ - (void)displayMessage:(OSInAppMessage *)message {
275288
}
276289

277290
self.isInAppMessageShowing = true;
278-
[self showAndImpressMessage:message];
291+
[self showMessage:message];
279292
}
280293

281-
- (void)showAndImpressMessage:(OSInAppMessage *)message {
294+
- (void)showMessage:(OSInAppMessage *)message {
282295
self.viewController = [[OSInAppMessageViewController alloc] initWithMessage:message delegate:self];
283296
if (message.hasLiquid && !self.calledLoadTags) {
284297
self.viewController.waitForTags = YES;
285298
[self loadTags];
286299
}
287300
dispatch_async(dispatch_get_main_queue(), ^{
288-
[[self.viewController view] setNeedsLayout];
289-
[self messageViewImpressionRequest:message];
301+
[[self.viewController view] setNeedsLayout];
290302
});
291303
}
292304

305+
- (void)sendMessageImpression:(OSInAppMessage *)message {
306+
if ([self shouldSendImpression:message]) {
307+
dispatch_async(dispatch_get_main_queue(), ^{
308+
[self messageViewImpressionRequest:message];
309+
});
310+
}
311+
}
312+
293313
- (void)loadTags {
294314
self.calledLoadTags = YES;
295315
[OneSignal getTags:^(NSDictionary *result) {
@@ -677,6 +697,10 @@ - (void)messageViewDidDisplayPage:(OSInAppMessage *)message withPageId:(NSString
677697
});
678698
}
679699

700+
- (void)messageIsNotActive:(OSInAppMessage *)message {
701+
[self deleteInactiveMessage:message];
702+
}
703+
680704
/*
681705
* Show the developer what will happen with a non IAM preview
682706
*/
@@ -754,12 +778,16 @@ - (void)sendOutcomes:(NSArray<OSInAppMessageOutcome *>*)outcomes forMessageId:(N
754778
/*
755779
This method must be called on the Main thread
756780
*/
757-
- (void)webViewContentFinishedLoading {
781+
- (void)webViewContentFinishedLoading:(OSInAppMessage *)message {
758782
if (!self.viewController) {
759783
[self evaluateMessages];
760784
return;
761785
}
762786

787+
if (message) {
788+
[self sendMessageImpression:message];
789+
}
790+
763791
if (!self.window) {
764792
self.window = [[UIWindow alloc] init];
765793
self.window.windowLevel = UIWindowLevelAlert;
@@ -845,7 +873,7 @@ - (id)getTriggerValueForKey:(NSString *)key { return 0; }
845873
#pragma mark OSInAppMessageViewControllerDelegate Methods
846874
- (void)messageViewControllerWasDismissed {}
847875
- (void)messageViewDidSelectAction:(OSInAppMessage *)message withAction:(OSInAppMessageAction *)action {}
848-
- (void)webViewContentFinishedLoading {}
876+
- (void)webViewContentFinishedLoading:(OSInAppMessage *)message {}
849877
#pragma mark OSTriggerControllerDelegate Methods
850878
- (void)triggerConditionChanged {}
851879
- (void)dynamicTriggerCompleted:(NSString *)triggerId {}

iOS_SDK/OneSignalSDK/UnitTests/InAppMessagingIntegrationTests.m

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,8 @@ - (void)testIAMWithRedisplay {
388388
}];
389389

390390
[OneSignal addTrigger:@"prop1" withValue:@2];
391+
392+
[UnitTestCommonMethods runLongBackgroundThreads];
391393

392394
// IAM should be shown instantly and be within the messageDisplayQueue
393395
XCTAssertEqual(1, OSMessagingControllerOverrider.messageDisplayQueue.count);
@@ -420,7 +422,10 @@ - (void)testIAMWithRedisplay {
420422

421423
[OneSignal addTrigger:@"prop1" withValue:@2];
422424

425+
[UnitTestCommonMethods runLongBackgroundThreads];
426+
423427
XCTAssertEqual(1, OSMessagingControllerOverrider.messageDisplayQueue.count);
428+
424429
// The display should cause an new "viewed" API request
425430
XCTAssertEqualObjects(OneSignalClientOverrider.lastHTTPRequestType, NSStringFromClass([OSRequestInAppMessageViewed class]));
426431

@@ -747,9 +752,11 @@ - (void)testIAMViewedLaunchesViewedAPIRequest {
747752
// the trigger should immediately evaluate to true and should
748753
// be shown once the SDK is fully initialized.
749754
[OneSignalClientOverrider setMockResponseForRequest:NSStringFromClass([OSRequestRegisterUser class]) withResponse:registrationResponse];
750-
755+
751756
[UnitTestCommonMethods initOneSignal_andThreadWait];
752757

758+
[UnitTestCommonMethods runLongBackgroundThreads];
759+
753760
// the message should now be displayed
754761
XCTAssertEqualObjects(OneSignalClientOverrider.lastHTTPRequestType, NSStringFromClass([OSRequestInAppMessageViewed class]));
755762
}

iOS_SDK/OneSignalSDK/UnitTests/Shadows/OSMessagingControllerOverrider.m

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,23 @@ @implementation OSMessagingControllerOverrider
8787
+ (void)load {
8888
#pragma clang diagnostic push
8989
#pragma clang diagnostic ignored "-Wundeclared-selector"
90-
injectToProperClass(@selector(overrideShowAndImpressMessage:), @selector(showAndImpressMessage:), @[], [OSMessagingControllerOverrider class], [OSMessagingController class]);
90+
injectToProperClass(@selector(overrideShowMessage:), @selector(showMessage:), @[], [OSMessagingControllerOverrider class], [OSMessagingController class]);
91+
injectToProperClass(@selector(overrideWebViewContentFinishedLoading:), @selector(webViewContentFinishedLoading:), @[], [OSMessagingControllerOverrider class], [OSMessagingController class]);
9192
#pragma clang diagnostic pop
9293
}
9394

94-
- (void)overrideShowAndImpressMessage:(OSInAppMessage *)message {
95+
- (void)overrideShowMessage:(OSInAppMessage *)message {
9596
dispatch_async(dispatch_get_main_queue(), ^{
9697
let viewController = [[OSInAppMessageViewController alloc] initWithMessage:message delegate:OSMessagingController.self];
9798
[viewController viewDidLoad];
99+
[OSMessagingController.sharedInstance webViewContentFinishedLoading:message];
98100
});
99-
[OSMessagingController.sharedInstance messageViewImpressionRequest:message];
101+
}
102+
103+
- (void)overrideWebViewContentFinishedLoading:(OSInAppMessage *)message {
104+
if (message) {
105+
[OSMessagingController.sharedInstance messageViewImpressionRequest:message];
106+
}
100107
}
101108

102109
+ (void)dismissCurrentMessage {

iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ withNotificationWillShowInForegroundHandler:(OSNotificationWillShowInForegroundB
5959
withNotificationOpenedHandler:(OSNotificationOpenedBlock)notificationOpenedDelegate;
6060

6161
+ (void)runBackgroundThreads;
62+
+ (void)runLongBackgroundThreads;
6263
+ (void)clearStateForAppRestart:(XCTestCase *)testCase;
6364
+ (void)beforeAllTest;
6465
+ (void)beforeAllTest:(XCTestCase *)testCase;

iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.m

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,23 @@ + (void)initOneSignalWithAppId:(NSString*)appId
148148
[OneSignal setNotificationOpenedHandler:notificationOpenedDelegate];
149149
}
150150

151+
/*
152+
Runs any blocks passed to dispatch_async() with delays after each call
153+
This will allow more time for chained async methods to complete
154+
*/
155+
+ (void)runLongBackgroundThreads {
156+
NSLog(@"START runLongBackgroundThreads");
157+
158+
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05]];
159+
160+
for(int i = 0; i < 10; i++) {
161+
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
162+
[UnitTestCommonMethods runThreadsOnEachQueue];
163+
}
164+
165+
NSLog(@"END runLongBackgroundThreads");
166+
}
167+
151168
/*
152169
Runs any blocks passed to dispatch_async()
153170
*/
@@ -156,32 +173,36 @@ + (void)runBackgroundThreads {
156173

157174
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05]];
158175

159-
// the httpQueue makes sure all HTTP request mocks are sync'ed
160-
161-
dispatch_queue_t registerUserQueue, notifSettingsQueue;
162176
for(int i = 0; i < 10; i++) {
163-
[OneSignalHelperOverrider runBackgroundThreads];
164-
165-
notifSettingsQueue = [OneSignalNotificationSettingsIOS10 getQueue];
166-
if (notifSettingsQueue)
167-
dispatch_sync(notifSettingsQueue, ^{});
168-
169-
registerUserQueue = [OneSignal getRegisterQueue];
170-
if (registerUserQueue)
171-
dispatch_sync(registerUserQueue, ^{});
172-
173-
[OneSignalClientOverrider runBackgroundThreads];
174-
175-
[UNUserNotificationCenterOverrider runBackgroundThreads];
176-
177-
dispatch_barrier_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{});
178-
179-
[UIApplicationOverrider runBackgroundThreads];
177+
[UnitTestCommonMethods runThreadsOnEachQueue];
180178
}
181179

182180
NSLog(@"END runBackgroundThreads");
183181
}
184182

183+
+ (void)runThreadsOnEachQueue {
184+
// the httpQueue makes sure all HTTP request mocks are sync'ed
185+
dispatch_queue_t registerUserQueue, notifSettingsQueue;
186+
187+
[OneSignalHelperOverrider runBackgroundThreads];
188+
189+
notifSettingsQueue = [OneSignalNotificationSettingsIOS10 getQueue];
190+
if (notifSettingsQueue)
191+
dispatch_sync(notifSettingsQueue, ^{});
192+
193+
registerUserQueue = [OneSignal getRegisterQueue];
194+
if (registerUserQueue)
195+
dispatch_sync(registerUserQueue, ^{});
196+
197+
[OneSignalClientOverrider runBackgroundThreads];
198+
199+
[UNUserNotificationCenterOverrider runBackgroundThreads];
200+
201+
dispatch_barrier_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{});
202+
203+
[UIApplicationOverrider runBackgroundThreads];
204+
}
205+
185206
+ (void)clearStateForAppRestart:(XCTestCase *)testCase {
186207
NSLog(@"======= APP RESTART ======\n\n");
187208

0 commit comments

Comments
 (0)