iOS:在一段时间后在后台终止应用程序

时间:2012-01-17 12:51:14

标签: objective-c ios nstimer

我正在尝试在我的应用中实现密码锁定功能,让用户可以选择在重新进入需要密码之前必须经过多长时间(类似于操作系统的密码功能)。因此,例如,用户可能能够在将应用退出到后台5,10,20分钟后选择他们想要密码。

我试图以不同的方式处理密码视图,但通常很难找出呈现它的最佳方式,所以我有一个想法,也许最好在之后终止应用程序时间到了,因此我只需要在启动应用程序时显示密码屏幕。

这可能吗?关于如何处理这个问题我有两个想法。

1)在app委托中有一个NSTimer,当app进入后台时启动它,然后当/如果计时器达到设定的分钟数,然后终止应用程序?我可以看到一些问题,例如,如果操作系统终止应用程序以比计时器结束更快地释放内存。虽然那不是一个大问题。

2)当应用程序进入后台时设置NSDate的实例。然后,当应用程序启动时,查看此日期是否超过x分钟前,并根据该日期显示密码输入屏幕。

我觉得这两个都有点不对劲。我对Timers,RunLoops等缺乏经验,所以任何建议都表示赞赏。

3 个答案:

答案 0 :(得分:2)

选项2似乎是我们成功使用的一个很好的解决方案。

答案 1 :(得分:2)

选项2.使用ApplicationDelegate生命周期方法来驱动它。

  • 应用中:didFinishLaunchingWithOptions:
  • applicationDidBecomeActive:
  • applicationWillResignActive:
  • applicationDidEnterBackground:
  • applicationWillEnterForeground:
  • applicationWillTerminate:
  • 的applicationDidFinishLaunching:

在applicationWillResignActive方法中,将当前时间戳保存到UserDefaults,并在applicationWillEnterForeground中检查当前时间,如果密码间隔已经过去,则显示您的密码。 (可能最好清除活动时的时间戳,以尽量减少接听电话和短信时误触发的可能性等)

根据您的敏感度,您可能需要在进入前景之前准备视图以隐藏敏感数据,因此它们不会在解锁状态下返回。

答案 2 :(得分:1)

你可以跟随两者以获得更好的结果。例如,当应用程序从didFinishLaunchingWithOptions激活时使用选项2,当应用程序启用时,使用选项1 - (void)applicationDidBecomeActive:(UIApplication *)应用程序或 - (void)applicationWillEnterForeground:(UIApplication *)应用程序 选项1 - 最简单的方法是在后台运行循环上安排NSTimer。我建议在您的应用程序委托上实现以下代码,并从applicationWillResignActive调用setupTimer:。

- (void)applicationWillResignActive:(UIApplication *)application
{
[self performSelectorInBackground:@selector(setupTimerThread) withObject:nil];
}
-(void)setupTimerThread;
{
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  NSTimer* timer = [NSTimer timerWithTimeInterval:10 * 60 target:self selector:@selector(triggerTimer:) userInfo:nil repeats:YES];
  NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
  [runLoop addTimer:timer forModes:NSRunLoopCommonModes];
  [runLoop run];
  [pool release];
}

-(void)triggerTimer:(NSTimer*)timer;
{
  // Do your stuff
}
在appDelegate .h

 UIBackgroundTaskIdentifier bgTask;
在appDelegate .m

- (void)applicationDidEnterBackground:(UIApplication *)application
 {

UIApplication*    app = [UIApplication sharedApplication];

// Request permission to run in the background. Provide an
// expiration handler in case the task runs long.
NSAssert(bgTask == UIBackgroundTaskInvalid, nil);

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    // Synchronize the cleanup call on the main thread in case
    // the task actually finishes at around the same time.
    dispatch_async(dispatch_get_main_queue(), ^{
        if (bgTask != UIBackgroundTaskInvalid)
        {
            [app endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;

        }
   });
}];

// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Do the work associated with the task.

    // Synchronize the cleanup call on the main thread in case
    // the expiration handler is fired at the same time.
    dispatch_async(dispatch_get_main_queue(), ^{
        if (bgTask != UIBackgroundTaskInvalid)
        {
            [app endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;

        }
    });
});
NSLog(@"app entering background");
/*
 Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
 If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
 */

}
或者你可以在后台线程上使用类似的东西运行NS​​Timer(我故意泄漏线程对象):

-(void)startTimerThread;
{
  NSThread* thread = [[NSThread alloc] initWithTarget:self selector:@selector(setupTimerThread) withObject:nil];
  [thread start];
}

尝试使用上面的代码。我们使用这两个选项它对我们来说很好。祝你好运