iOS: завершение приложения в фоновом режиме через определенный промежуток времени - PullRequest
3 голосов
/ 17 января 2012

Я пытаюсь реализовать функцию блокировки паролем в моем приложении, которая позволяет пользователю выбирать, сколько времени должно пройти, прежде чем пароль потребуется для повторного входа (аналогично функциональности пароля в ОС).Так, например, пользователь может выбрать, что он должен требовать пароль через 5, 10, 20 минут после выхода из приложения в фоновом режиме.

Я пытался представить представление пароля по-разному, но зачастую трудно определить лучший способ его представления, и поэтому у меня возникла мысль, что, возможно, лучше прекратитьприложение после того, как время истекло, и поэтому я должен был бы только показать экран пароля при запуске приложения.

Возможно ли это сделать?У меня было две мысли о способах решения этой проблемы.

1) Имейте NSTimer в делегате приложения, запускайте его, когда приложение переходит в фоновый режим, а затем, когда / если таймер достигает заданного количества минут,затем прекратить приложение?Я мог видеть, что с этим что-то пошло не так, например, если ОС закрыла приложение, чтобы освободить память раньше, чем закончился таймер.Хотя это не будет большой проблемой.

2) Установите экземпляр NSDate, когда приложение переходит в фоновый режим.Затем, когда приложение запускается, посмотрите, не превышает ли эта дата более x минут назад, и представьте экран ввода пароля в зависимости от этого.

Я чувствую, что оба они немного отключены.У меня нет опыта работы с таймерами, циклами запуска и т. Д., Поэтому любые советы приветствуются.

Ответы [ 3 ]

2 голосов
/ 17 января 2012

Вариант 2. Используйте методы ApplicationDelegate Lifecycle для его управления.

  • применение: didFinishLaunchingWithOptions:
  • applicationDidBecomeActive:
  • applicationWillResignActive:
  • applicationDidEnterBackground:
  • applicationWillEnterForeground:
  • applicationWillTerminate:
  • applicationDidFinishLaunching:

В методе applicationWillResignActive сохраните текущую временную метку в пользовательских значениях UserDefaults, а в applicationWillEnterForeground проверьте ее по текущему времени и, если интервал пароля прошел, представьте свой пароль. (вероятно, лучше всего очистить отметку времени, когда вы активны, чтобы минимизировать вероятность ложного срабатывания при получении вызовов, SMS и т. д.)

В зависимости от чувствительности вы можете подготовить свои представления перед входом на передний план, чтобы скрыть конфиденциальные данные, чтобы они не возвращались в разблокированном состоянии.

2 голосов
/ 17 января 2012

Вариант 2 представляется хорошим решением, которое мы успешно использовали.

1 голос
/ 17 января 2012

вы можете следовать обоим для лучшего результата.Например, используйте опцию 2, когда приложение активно из didFinishLaunchingWithOptions: и опцию 1, когда приложение активируется из - (void) applicationDidBecomeActive: (UIApplication *) application или - (void) applicationWillEnterForeground: (UIApplication *) Опция приложения 1-Самый простой способ - это запланироватьNSTimer на фоне запуска цикла.Я полагаю, что следующий код реализован в вашем делегате приложения, и что вы вызываете setupTimer из applicationWillResignActive:.

- (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.
 */

}
ИЛИ вы можете запустить NSTimer в фоновом потоке с помощью чего-то вроде этого (я намеренно пропускаю объект потока):

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

попробуйте этот код выше,мы используем оба варианта, он прекрасно работает для нас.удачи

...