Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS UILocalNotification's action button crashes and corrupts app data

Minor update to our app was released, this version had also changed its App ID from a unique ID to our Team ID by Apple support.

According to Apple, changing to the use of Team ID should only reset keychain access, we don't use the keychain so it shouldn't have any effect on our app.

But since the update was released, some of our users on production have been experiencing corruption of their app data. This happens only when they respond to a local notification using an action button from the Notification Center or lock screen. It may happen on all iOS versions supported.

Users experiencing this have another symptom, they receive two local notifications instead of just one, but the app only see one notification. Further more, these notifications still won't go away after disabling notifications and cancellation using [[UIApplication sharedApplication] cancelAllLocalNotifications].

These duplicate notification were scheduled before the app was updated from the App Store, but after update app lost control over them for some users. This issue is described in detail in this question.

The biggest clue may lay in crash reports received from Apple -

Incident Identifier: ED0E9C.............74B38C
CrashReporter Key:   ae05b............dbc46
Hardware Model:      iPhone4,1
Process:             MY_APP [444]
Path:                /private/var/mobile/Containers/Bundle/Application/65324..................8616/MY_APP.app/MY_APP
Identifier:          com.mycompany.myapp
Version:             X.X
Code Type:           ARM (Native)
Parent Process:      launchd [1]

Date/Time:           2015-10-27 21:45:24.24 -0500
Launch Time:         2015-10-27 21:45:20.20 -0500
OS Version:          iOS 9.1 (13B143)
Report Version:      104

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Triggered by Thread:  0

Last Exception Backtrace:
0   CoreFoundation                  0x244b3676 __exceptionPreprocess + 122 (NSException.m:162)
1   libobjc.A.dylib                 0x3582ee12 objc_exception_throw + 34 (objc-exception.mm:531)
2   CoreFoundation                  0x244b354c +[NSException raise:format:arguments:] + 100 (NSException.m:131)
3   Foundation                      0x25240bc4 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 88 (NSException.m:152)
4   UIKit                           0x28840754 -[UIApplication _runWithMainScene:transitionContext:completion:] + 2928 (UIApplication.m:3299)
5   UIKit                           0x28853a48 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke3218 + 32 (UIApplication.m:11920)
6   UIKit                           0x2883d71e -[UIApplication workspaceDidEndTransaction:] + 130 (UIApplication.m:2648)
7   FrontBoardServices              0x2c52dca2 -[FBSSerialQueue _performNext] + 226 (FBSSerialQueue.m:157)
8   FrontBoardServices              0x2c52df94 -[FBSSerialQueue _performNextFromRunLoopSource] + 44 (FBSSerialQueue.m:204)
9   CoreFoundation                  0x24476bfa __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 10 (CFRunLoop.c:1761)
10  CoreFoundation                  0x244767e8 __CFRunLoopDoSources0 + 448 (CFRunLoop.c:1807)
11  CoreFoundation                  0x24474b56 __CFRunLoopRun + 790 (CFRunLoop.c:2536)
12  CoreFoundation                  0x243c8114 CFRunLoopRunSpecific + 516 (CFRunLoop.c:2814)
13  CoreFoundation                  0x243c7f00 CFRunLoopRunInMode + 104 (CFRunLoop.c:2844)
14  UIKit                           0x28610208 -[UIApplication _run] + 520 (UIApplication.m:2489)
15  UIKit                           0x2860af10 UIApplicationMain + 140 (UIApplication.m:3665)
16  MY_APP                          0xc4972 main + 22 (main.m:14)
17  libdyld.dylib                   0x35f9d86e tlv_get_addr + 42 (threadLocalHelpers.s:310)

It has a stacktrace exactly the same as in this question, which happens when users respond to a push notification. Crash during app load may explain the corrupted app data.

As seen in the stacktrace this crash is not caused by our code, we haven't changed anything in the code, it has been working well before the App ID change and it happens to ~2% of our users.

Here's the code that handles action buttons of notifications -

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler {

    @try {
        if (notification) {
            NSDate *alarmTime = notification.userInfo ? [notification.userInfo objectForKey:@"time"] : nil;
            [logic saveAlarmTime:alarmTime takenAt:[NSDate date]];
        }
    }
    @catch (NSException *exception) {
        NSLog(@"Exception: %@", [exception description]);
    }
    @finally {
        completionHandler();
    }
}

What causes this crash?

(I know that it's thrown in -[UIApplication _runWithMainScene:transitionContext:completion:] + 2928 (UIApplication.m:3299), question is what's in there that causes this to crash.)

like image 531
Kof Avatar asked Oct 28 '15 06:10

Kof


1 Answers

It is possible that this exception is not related to responding to a notification through an action button in the first place. This stack trace indicates a problem while loading the app, but has several possible causes, anything that crashes the app while loading will cause this.

For instance, it may occur when the app loads and its window doesn't have a root view controller assigned. May also happen if it was added using addSubview instead of setRootViewController, as seen here.

You'll have to verify with users that experienced this crash what they were doing, if indeed they've only responded to a local notification action button, or they have experienced the crash while opening the app.

like image 117
gala Avatar answered Nov 15 '22 06:11

gala