iOS UILocalNotification的操作按钮会崩溃并破坏应用数据

时间:2015-10-28 06:53:05

标签: ios objective-c notifications uilocalnotification nsnotificationcenter

我们的应用程序的次要更新已发布,此版本还已将Apple App ID从唯一ID更改为我们的团队ID。

According to Apple,更改为使用团队ID只应重置密钥链访问权限,我们不使用密钥链,因此不应对我们的应用程序产生任何影响。

但是自从更新发布以来,一些我们的生产用户已经遇到了他们的应用数据损坏。仅当他们使用通知中心或锁定屏幕中的操作按钮响应本地通知时才会发生这种情况。它可能会在所有支持的iOS版本上发生。

遇到此问题的用户有另一种症状,他们会收到两个本地通知,而不只是一个,但该应用只会看到一个通知。此外,使用[[UIApplication sharedApplication] cancelAllLocalNotifications]禁用通知和取消后,这些通知仍然不会消失。

这些重复通知是在应用程序从App Store更新之前安排的,但在更新应用程序失去对某些用户的控制权之后。详细描述了此问题in this question

最大的线索可能在于从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)

它有一个与this question完全相同的堆栈跟踪,当用户响应推送通知时会发生这种情况。应用加载期间崩溃可能会解释已损坏的应用数据。

正如在堆栈跟踪中看到的,这次崩溃不是由我们的代码引起的,我们没有更改代码中的任何内容,它在应用程序ID更改之前一直运行良好,并且它发生在~2%的用户中。

以下是处理通知操作按钮的代码 -

- (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();
    }
}

导致此次崩溃的原因是什么?

(我知道它在-[UIApplication _runWithMainScene:transitionContext:completion:] + 2928 (UIApplication.m:3299)中被抛出,问题是那里导致崩溃的原因。)

3 个答案:

答案 0 :(得分:4)

此异常可能与首先通过操作按钮响应通知无关。此堆栈跟踪指示加载应用程序时出现问题,但有几个可能的原因,任何在加载时崩溃应用程序都会导致此问题。

例如,当应用加载并且其窗口没有分配根视图控制器时,可能会发生这种情况。如果使用addSubview而不是setRootViewController添加,则可能会发生,如here所示。

您必须与经历此次崩溃的用户核实他们正在做什么,如果他们确实只响应了本地通知操作按钮,或者他们在打开应用时遇到了崩溃。

答案 1 :(得分:0)

数据损坏的原因是"数据保护" 选项。它可以从Xcode或iOS开发人员门户网站的Identifiers - >下启用。应用ID。

Xcode data protection option

它有三种状态:"完全保护","受保护除非打开"和#34;受保护直到第一次用户身份验证"。只要数据受到保护,甚至应用程序都无法访问数据。

iOS Developer Portal

例如,如果"完全保护"在我们的案例中被选中,并且正在运行诸如通知的操作按钮之类的后台进程,由于权限错误,Core Data无法访问数据库。

我仍然不确定为什么它会破坏数据,有时会定义" Permission defined"错误不会显示但仍然无法读取SQLite文件。也许它也写在文件上,但由于加密是ON,它破坏了文件。

解决方案是选择"受保护直到第一次用户身份验证"或禁用数据保护。

相关问题:CoreData errors/exceptions when app work in background mode

Apple's iOS Security PDF

答案 2 :(得分:-1)

此行导致崩溃:

[UIApplication _runWithMainScene:transitionContext:completion:] + 2928 (UIApplication.m:3299)

如果某个团队针对某个应用进行了更改,该应用的唯一应用标识符也会发生变化,因为它是该应用的一部分。本地通知使用唯一的应用标识符。所以它基本上确实是Apple的一个错误,因为iOS应该识别出一个没有相应应用程序的通知。这也是你的崩溃,因为你启动但你没有得到你通常会使用的对象。

盲目猜测,因为我不知道你的代码。响应本地通知时,在继续之前检查对象和所有相关数据是否存在。你知道,比如:

if (object) {
    //do the stuff
} else { 
    // do nothing
}

(比例外情况更好......)

对于不再属于您的通知 - 用户可以自行删除它们。只要确保你不崩溃 - 什么都不做就好了。通常ppl会在某个时候自行删除它们然后清理它们的通知中心。