拥有NSTimer运行背景

时间:2014-10-14 13:11:51

标签: ios xcode nstimer background-process

我已经看过数百种如何让NSTimer在后台运行的解决方案。

我知道这是可能的,只需看看像Strava和Runkepper这样的应用程序就可以跟踪你锻炼的时间。

但这样做的最佳实践解决方案是什么?我无法为此找到一个协调解决方案。

另外,我希望NSTimer可以在不同的UIViewControllers中使用。这是如何做到的最佳做法?

谢谢! :)

3 个答案:

答案 0 :(得分:2)

NSTimers不在后台运行。获得背景后,存储当前时间和计时器的经过时间。当您返回前台时,您将设置一个新计时器,使用这两个信息来设置需要反映总耗用时间的任何状态或数据。 要在viewCOntroller之间共享,只需要一个对象实现此计时器,并在其上公开一个属性(例如elapsedTime),每个时间间隔都会更新。然后,您可以让viewCO控制器(具有对该对象的引用)观察该属性以进行更改。

答案 1 :(得分:2)

您可以在您的应用程序中尝试此代码NSTimers不在后台运行。加入苹果但我们强行尝试只有3个薄荷 AppDelegate.h

@property (nonatomic, unsafe_unretained) UIBackgroundTaskIdentifier backgroundTaskIdentifier;
@property (nonatomic, strong) NSTimer *myTimer;
- (BOOL) isMultitaskingSupported;
- (void) timerMethod:(NSTimer *)paramSender;

AppDelegate.m

 - (void)applicationDidEnterBackground:(UIApplication *)application {
        // 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.

        if ([self isMultitaskingSupported] == NO)
        {
            return;
        }
        self.myTimer =[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerMethod:) userInfo:nil
                                        repeats:YES];
        self.backgroundTaskIdentifier =[application beginBackgroundTaskWithExpirationHandler:^(void) {
            [self endBackgroundTask];
        }];
    }

pragma mark - NSTimer进程

- (BOOL) isMultitaskingSupported
{
    BOOL result = NO;
    if ([[UIDevice currentDevice]
         respondsToSelector:@selector(isMultitaskingSupported)]){ result = [[UIDevice currentDevice] isMultitaskingSupported];
    }
    return result;
}


- (void) timerMethod:(NSTimer *)paramSender{

    NSTimeInterval backgroundTimeRemaining =
    [[UIApplication sharedApplication] backgroundTimeRemaining];
    if (backgroundTimeRemaining == DBL_MAX)
    {
        NSLog(@"Background Time Remaining = Undetermined");
    }
    else
    {
        NSLog(@"Background Time Remaining = %.02f Seconds",backgroundTimeRemaining);
    }
}
- (void) endBackgroundTask
{
    dispatch_queue_t mainQueue = dispatch_get_main_queue(); __weak AppDelegate *weakSelf = self;
    dispatch_async(mainQueue, ^(void) { AppDelegate *strongSelf = weakSelf; if (strongSelf != nil){
        [strongSelf.myTimer invalidate];
        [[UIApplication sharedApplication]
         endBackgroundTask:self.backgroundTaskIdentifier];
        strongSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
    } });
}

enter image description here

答案 2 :(得分:1)

正如评论中指出的那样,NSTimer在后​​台工作不起作用,iOS上的后台执行相当棘手,仅在某些情况下有效,请查看有关主题的Apple Docs,也this is an excellent read获得更多背景知识。

至于你的情况,听起来好像你想使用UILocalNotification。我从你的评论中了解到: I want to have a timer running while the app is not in the foreground. Just like Apples own timer app.

Apple的计时器应用使用UILocalNotification。它为您提供了一种方法来安排将在某个时间点出现给用户的通知,无论该应用程序是在前台还是后台!您在应用中所要做的就是安排通知,例如:像这样:

UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = dateTime;
localNotification.alertBody = [NSString stringWithFormat:@"Alert Fired at %@", dateTime];
localNotification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification]; 

然后iOS将为您处理剩下的事情:)