区分iPhone应用程序崩溃和被杀死

Gap*_*ton 8 iphone crash objective-c detection ios

您好我打算开发一款简单的iPhone游戏.我希望能够区分真正的崩溃和用户杀死应用程序(通过双击主屏幕并长按它来杀死它).

有人可以了解用户通过多任务栏杀死应用程序时究竟发生了什么.

ser*_*gio 15

如果您的应用在后台并在用户杀死时暂停,则不会收到任何通知.这占了大多数情况.

如果您的应用当前正在后台运行(只有非常特定类别的应用可以执行此操作),那么它会收到applicationWillTerminate.

事实上,Apple非常清楚你应该在进入后台之前保存任何相关数据.看看这个("响应申请终止"一章):

即使您使用iOS SDK 4及更高版本开发应用程序,您仍然必须准备好在没有任何通知的情况下杀死您的应用程序.用户可以使用多任务UI显式地终止应用程序.此外,如果内存受限制,系统可能会从内存中删除应用程序以腾出更多空间.如果您的应用程序当前处于暂停状态,系统将终止您的应用程序并将其从内存中删除而不另行通知.但是,如果您的应用程序当前正在后台运行状态(换句话说,未挂起),系统将调用应用程序委托的applicationWillTerminate:方法.您的应用程序无法从此方法请求额外的后台执行时间.

编辑:

关于"说对不起"的事情......

你可以在下次发布时做到这一点.只需存储一个密钥NSUserDefaults并在应用程序进入后台时将其删除(我希望所有这些听起来都很熟悉,否则请查看UIApplicationDelegate协议).

当应用程序启动时,您检查密钥; 如果它在那里,那么应用程序没有被用户关闭; 如果应用程序不在那里,那么用户至少将应用程序移动到后台并且没有经历任何突然终止...


Sko*_*tch 7

对于iOS6及更高版本,有一种方法可以做到这一点.状态恢复的一个副作用是,当恢复期间发生崩溃或用户手动杀死应用程序时,它将删除状态.您可以利用此优势来检测用户手动终止应用程序.

文档:

请注意,当用户强制退出应用程序时,系统会自动删除应用程序的保留状态.在应用程序被杀死时删除保留的状态信息是一种安全预防措施.(如果应用程序在启动时崩溃,系统也会删除保留状态作为类似的安全预防措施.)如果要测试应用程序恢复其状态的能力,则在调试期间不应使用多任务栏来终止应用程序.相反,使用Xcode杀死应用程序或通过安装临时命令或手势以按需调用exit来以编程方式终止应用程序.

以下代码假定您已经BOOL调用了崩溃检测_didCrashInLastSession.获得此值的方法有很多种,例如第三方库.在您的代码中调用该方法[self getLaunchType]以查看您正在处理的启动类型并相应地对其进行操作.将以下内容放入AppDelegate.m中:

typedef NS_ENUM(NSInteger, LaunchType) {
    LaunchTypeUnknown,
    LaunchTypeNewInstall,
    LaunchTypeNormalLaunch,
    LaunchTypeCrashedLastSession,
    LaunchTypeUserManualQuit,
};

static BOOL hadStateToRestore = NO;
static NSString * const kAppHasEverRunKey = @"appHasEverRun";

- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder
{
    // Called when going into the background
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kAppHasEverRunKey];
    [[NSUserDefaults standardUserDefaults] synchronize];

    return YES;
}

- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder
{
    // Called on start up
    hadStateToRestore = YES;
    return YES;
}

- (LaunchType)getLaunchType
{
    if (_didCrashInLastSession) {
        return LaunchTypeCrashedLastSession;
    }

    if (![[NSUserDefaults standardUserDefaults] boolForKey:kAppHasEverRunKey]) {
        return LaunchTypeNewInstall;
    }

    if (!hadStateToRestore) {
        return LaunchTypeUserManualQuit;
    }

    return LaunchTypeNormalLaunch;
}
Run Code Online (Sandbox Code Playgroud)

更新:至少有一个第三方SDK破坏了这项技术:Urban Airship.