1

出于某种原因,我的计时器只在前台运行。我在这里搜索了解决方案,但找不到任何好的解决方案。我的计时器使用核心数据,每次递减后都会保存我的 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];
}

我真的很感激一些指导,让我的计时器在后台工作(就像苹果的计时器一样)。我不确定如何使用 NSDateComponents,因为即使应用程序在后台,我也需要更新 testTask.timeInterval ..

4

2 回答 2

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];

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

于 2013-08-04T11:09:43.277 回答
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) 的应用程序
  • 需要下载和处理新内容的报亭应用
  • 从外部配件接收定期更新的应用程序

取自这里

我建议你阅读这篇关于后台任务的文章。

于 2013-08-04T11:18:00.650 回答