Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions JRFMemoryNoodler/JRFMemoryNoodler.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,20 @@ typedef BOOL (^JRFCrashDetector)();
+ (void)beginMonitoringMemoryEventsWithHandler:(nonnull JRFOutOfMemoryEventHandler)handler
crashDetector:(nullable JRFCrashDetector)crashDetector;


/**
You should call this when your application receives a silent push notification. This will allow JRFMemoryNoodler to track an application launch that occurred from a silent push notification.
Call this if your application is not in the foreground and during:
`- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))fetchCompletionHandler`
*/
+ (void)markSilentPushNotificationEvent;

/**
You should call this when your application wakes up to perform work in the background. This will allow JRFMemoryNoodler to track an application launch that occurred from a silent push notification.
Call this during:
`- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))fetchCompletionHandler`
*/
+ (void)markBackgroundFetchEvent;

@end

22 changes: 21 additions & 1 deletion JRFMemoryNoodler/JRFMemoryNoodler.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
NSString *JRFAppWasInBackgroundKey = @"JRFAppWasInBackgroundKey";
NSString *JRFAppDidCrashKey = @"JRFAppDidCrashKey";
NSString *JRFPreviousOSVersionKey = @"JRFPreviousOSVersionKey";
NSString *JRFSilentPushNotificationKey = @"JRFSilentPushNotificationKey";
NSString *JRFBackgroundFetchKey = @"JRFBackgroundFetchKey";

static char *intentionalQuitPathname;

@implementation JRFMemoryNoodler
Expand Down Expand Up @@ -47,11 +50,14 @@ + (void)beginMonitoringMemoryEventsWithHandler:(JRFOutOfMemoryEventHandler)handl
// A file exists at the path, we had an intentional quit
didIntentionallyQuit = YES;
}

BOOL didCrash = detector();
BOOL didTerminate = [defaults boolForKey:JRFAppWasTerminatedKey];
BOOL didUpgradeApp = ![[self currentBundleVersion] isEqualToString:[self previousBundleVersion]];
BOOL didUpgradeOS = ![[self currentOSVersion] isEqualToString:[self previousOSVersion]];
if (!(didIntentionallyQuit || didCrash || didTerminate || didUpgradeApp || didUpgradeOS)) {
BOOL didReceiveSilentPushNotification = [[NSUserDefaults standardUserDefaults] boolForKey:JRFSilentPushNotificationKey];
BOOL didBackgroundFetch = [[NSUserDefaults standardUserDefaults] boolForKey:JRFBackgroundFetchKey];
if (!(didIntentionallyQuit || didCrash || didTerminate || didUpgradeApp || didUpgradeOS || didReceiveSilentPushNotification || didBackgroundFetch)) {
if (handler) {
BOOL wasInBackground = [[NSUserDefaults standardUserDefaults] boolForKey:JRFAppWasInBackgroundKey];
handler(!wasInBackground);
Expand All @@ -63,6 +69,8 @@ + (void)beginMonitoringMemoryEventsWithHandler:(JRFOutOfMemoryEventHandler)handl
[defaults setBool:NO forKey:JRFAppWasTerminatedKey];
[defaults setBool:NO forKey:JRFAppWasInBackgroundKey];
[defaults setBool:NO forKey:JRFAppDidCrashKey];
[defaults setBool:NO forKey:JRFSilentPushNotificationKey];
[defaults setBool:NO forKey:JRFBackgroundFetchKey];
[defaults synchronize];
// Remove intentional quit file
unlink(intentionalQuitPathname);
Expand Down Expand Up @@ -156,4 +164,16 @@ + (JRFCrashDetector)defaultCrashDetector {
};
}

#pragma mark - Silent Push Notifications

+ (void)markSilentPushNotificationEvent {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:JRFSilentPushNotificationKey];
}

#pragma mark - Background Fetch Notifications

+ (void)markBackgroundFetchEvent {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:JRFBackgroundFetchKey];
}

@end
10 changes: 10 additions & 0 deletions JRFMemoryNoodlerTests/JRFMemoryNoodlerTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ - (void)testBackgroundingTracksProperly {
[self checkMemoryNoodlerWithExpectation:NO shouldBeInForeground:NO didCrash:YES];
}

- (void)testSilentPushNotificationDoesNotTriggerOutOfMemoryWarning {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"JRFSilentPushNotificationKey"];
[self checkMemoryNoodlerWithExpectation:NO shouldBeInForeground:YES didCrash:NO];
}

- (void)testBackgroundFetchDoesNotTriggerOutOfMemoryWarning {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"JRFBackgroundFetchKey"];
[self checkMemoryNoodlerWithExpectation:NO shouldBeInForeground:YES didCrash:NO];
}

- (void)testIntentionalQuitPathNameIsStable {
const char *pathname1 = [JRFPathUtilities intentionalQuitPathname];
const char *pathname2 = [JRFPathUtilities intentionalQuitPathname];
Expand Down