我完全不理解,但是我的应用程序中的NSTimer
明显正在后台运行。我在计时器方法中放置了一个NSLog
,而且它在后台记录。这是使用iOS 4.2.1的iPhone 4。我已在Info.plist中声明了位置后台支持。
我阅读了文档和许多论坛上的讨论,它不应该是可能的。这是iOS的错误吗?还是未经记录的功能?我不想使用它,并在不久的将来发现,例如随着iOS 4.3的推出Apple默默地“修复”了它,导致应用程序无法正常工作。
有人知道更多关于它的信息吗?
我完全不理解,但是我的应用程序中的NSTimer
明显正在后台运行。我在计时器方法中放置了一个NSLog
,而且它在后台记录。这是使用iOS 4.2.1的iPhone 4。我已在Info.plist中声明了位置后台支持。
我阅读了文档和许多论坛上的讨论,它不应该是可能的。这是iOS的错误吗?还是未经记录的功能?我不想使用它,并在不久的将来发现,例如随着iOS 4.3的推出Apple默默地“修复”了它,导致应用程序无法正常工作。
有人知道更多关于它的信息吗?
NSTimer
会在主运行循环运行时触发。据我所知,苹果没有承诺取消预定计时器或阻止主运行循环的运行。当您转到后台时,您有责任取消预定计时器和释放资源。苹果不会为您做这件事情。但是如果您在不应该运行或使用太多秒钟的情况下运行,他们可能会杀死您。
系统中存在许多漏洞,可以允许应用在未获得授权的情况下运行。操作系统要防止这种情况将非常昂贵。但您不能依赖它。
当您处于后台执行模式时,您可以设置一个定时器。以下是一些技巧:
beginBackgroundTaskWithExpirationHandler
选择后台执行。- (void)viewDidLoad
{
// Avoid a retain cycle
__weak ViewController * weakSelf = self;
// Declare the start of a background task
// If you do not do this then the mainRunLoop will stop
// firing when the application enters the background
self.backgroundTaskIdentifier =
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundIdentifier];
}];
// Make sure you end the background task when you no longer need background execution:
// [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Since we are not on the main run loop this will NOT work:
[NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:@selector(timerDidFire:)
userInfo:nil
repeats:YES];
// This is because the |scheduledTimerWithTimeInterval| uses
// [NSRunLoop currentRunLoop] which will return a new background run loop
// which will not be currently running.
// Instead do this:
NSTimer * timer =
[NSTimer timerWithTimeInterval:0.5
target:weakSelf
selector:@selector(timerDidFire:)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer
forMode:NSDefaultRunLoopMode];
// or use |NSRunLoopCommonModes| if you want the timer to fire while scrolling
});
}
- (void) timerDidFire:(NSTimer *)timer
{
// This method might be called when the application is in the background.
// Ensure you do not do anything that will trigger the GPU (e.g. animations)
// See: http://developer.apple.com/library/ios/DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW47
NSLog(@"Timer did fire");
}
注意事项
beginBackgroundTaskWithExpirationHandler
将保持应用程序的运行达数分钟之久。 - RobbeginBackgroundTaskWithExpirationHandler
中...您为什么建议使用 beginBackgroundTaskWithExpirationHandler
? - mfaani
fireDate
已经过去,则它们会立即被触发。所以,我可以安全地依赖于fireDate
是否被传递,还是应该存储日期并进行比较? - mfaani