如何让我的计时器在后台运行,然后发送本地通知?

时间:2013-08-03 23:06:53

标签: iphone ios objective-c nstimer uilocalnotification

由于某种原因,我的计时器只在前台运行。我在这里寻找解决方案,但我找不到任何好的解决方案。我的计时器使用Core Data,每次减量后都会保存timeInterval。此外,我发送UILocalNotification,但这不起作用。我假设它不会发送警报视图,如果它在前台..这就是我现在拥有的:

-(IBAction)startTimer:(id)sender{
    if (timer == nil) {
        [startButton setTitle:@"Pause" forState:UIControlStateNormal];
       timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction:) userInfo:nil repeats:YES];
    } else {
        [startButton setTitle:@"Resume" forState:UIControlStateNormal];
        [timer invalidate];
        timer = nil;
    }

}
-(void)timerAction:(NSTimer *)t
{
    if(testTask.timeInterval == 0)
    {
        if (self.timer)
        {
            [self timerExpired];
            [self.timer invalidate];
            self.timer = nil;
        }
    }
    else
    {
        testTask.timeInterval--;
        NSError *error;
        if (![self.context save:&error]) {
            NSLog(@"couldn't save: %@", [error localizedDescription]);
        }
    }
    NSUInteger seconds = (NSUInteger)round(testTask.timeInterval);
    NSString *string = [NSString stringWithFormat:@"%02u:%02u:%02u",
                        seconds / 3600, (seconds / 60) % 60, seconds % 60];
    timerLabel.text = string;
    NSLog(@"%f", testTask.timeInterval);
}
-(void)timerExpired{
    UILocalNotification* localNotification = [[UILocalNotification alloc] init];
    localNotification.alertBody = @"Time is up";
    localNotification.alertAction = @"Ok";
    localNotification.timeZone = [NSTimeZone defaultTimeZone];
    [[UIApplication sharedApplication]presentLocalNotificationNow:localNotification];
}

我非常感谢让我的计时器在后台运行的一些指导(就像Apple的计时器一样)。我不确定如何使用NSDateComponents,因为即使应用程序在后台我也需要更新testTask.timeInterval ..

2 个答案:

答案 0 :(得分:6)

UIBackgroundTaskIdentifier bgTask =0;
UIApplication  *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    [app endBackgroundTask:bgTask];
}];

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0
           target:self
           selector:@selector(timerCountDown:)
           userInfo:nil
           repeats:YES];

现在使用此方法触发通知。计时器将在后台运行。

答案 1 :(得分:3)

正如Josh Caswell所写,你应该在应用程序进入后台之前保存你的计时器状态,然后当你的应用程序再次进入前台时检索它。

如果您需要在适当的时候发送本地通知,您可以在进入后台之前使用计时器的状态进行设置:

UILocalNotification *localNotification = [[UILocalNotification alloc] init];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];

[dateFormat setDateFormat:@"yyyyMMddHHmmss"];   
    NSDate *when = [dateFormat dateFromString:desiredTime];
// desiredTime -> time you want your local notification to be fired, take this from your timer before app enters the background

[dateFormat release];

localNotification.fireDate = when;
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.soundName = UILocalNotificationDefaultSoundName;

localNotification.alertBody = @"Hey";

[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];

[localNotification release];

编辑:在您的appDelegate中,您应该找到以下方法:

(1) - (void)applicationWillResignActive:(UIApplication *)application
(2) - (void)applicationDidEnterBackground:(UIApplication *)application
(3) - (void)applicationWillEnterForeground:(UIApplication *)application
(4) - (void)applicationDidBecomeActive:(UIApplication *)application
(5) - (void)applicationWillTerminate:(UIApplication *)application

这些内容专门用于管理应用状态发生变化时的行为。

在进入后台和恢复之前,您可以执行所需的一切。

在进入后台之前,您需要几秒钟来执行本地通知计划并保存计时器状态(例如使用NSUserDefaults)。

之后,如果由于以下原因之一而无法在后台运行,那么Apple可能会杀死您的应用:

  

实现长时间运行的后台任务适用于需要更多任务的任务   要执行的执行时间,您必须请求特定的权限   在后台运行它们而不会被暂停。仅在iOS中   允许特定的应用类型在后台运行:

     
      
  • 在后台播放用户可听内容的应用,   例如音乐播放器应用
  •   
  • 随时向用户通知其位置信息的应用,例如导航应用
  •   
  • 支持互联网协议语音(VoIP)的应用
  •   
  • 需要下载和处理新内容的报亭应用
  •   
  • 从外部附件接收定期更新的应用
  •   

取自here

我建议您阅读有关后台任务的this