Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 当应用程序处于后台时,是否预期NSTimer将启动?_Ios_Cocoa Touch_Background_Nstimer_Runloop - Fatal编程技术网

Ios 当应用程序处于后台时,是否预期NSTimer将启动?

Ios 当应用程序处于后台时,是否预期NSTimer将启动?,ios,cocoa-touch,background,nstimer,runloop,Ios,Cocoa Touch,Background,Nstimer,Runloop,我一点也不懂,但我的应用程序中的NSTimer肯定是在后台运行的。我有一个由计时器运行的NSLogin方法,它在后台记录。它在iPhone4和iOS 4.2.1上。我已经在Info.plist中声明了位置背景支持 我在这里和其他地方阅读了文件和许多讨论,这应该是不可能的。这是一个iOS错误吗?还是未记录的功能?我不想使用它,也不想在不久的将来发现,例如,随着iOS 4.3的推出,苹果悄悄地“修复”了它,应用程序将无法工作 有人知道更多吗?NSTimer将在主runloop运行时触发。据我所知,苹

我一点也不懂,但我的应用程序中的
NSTimer
肯定是在后台运行的。我有一个由计时器运行的
NSLog
in方法,它在后台记录。它在iPhone4和iOS 4.2.1上。我已经在Info.plist中声明了位置背景支持

我在这里和其他地方阅读了文件和许多讨论,这应该是不可能的。这是一个iOS错误吗?还是未记录的功能?我不想使用它,也不想在不久的将来发现,例如,随着iOS 4.3的推出,苹果悄悄地“修复”了它,应用程序将无法工作


有人知道更多吗?

NSTimer
将在主runloop运行时触发。据我所知,苹果并没有做出任何承诺,不安排计时器或阻止主runloop运行。当你移动到后台时,你有责任不安排你的计时器并释放资源。苹果不会为你做这件事。然而,他们可能会因为你不应该跑步或者用了太多的时间而杀了你

系统中存在许多漏洞,允许应用程序在未经授权的情况下运行。对于操作系统来说,防止这种情况的发生是非常昂贵的。但是您不能依赖它。

在后台执行模式下,您有一个计时器触发。这里有两个技巧:

  • 您需要选择在后台执行
    beginBackgroundTaskWithExpirationHandler
  • 如果在后台线程上创建NSTimer,则需要手动将其添加到mainRunLoop

注释

  • 应用程序只能在后台执行约10分钟-在此之后,计时器将停止启动
  • 从iOS 7开始,当设备被锁定时,它几乎会立即挂起前台应用程序。iOS 7应用程序锁定后,计时器将不会启动

好的,这对我来说已经足够了。谢谢我不知道我是否错过了什么。我不确定用它。我在观察你说的行为。我用计时器每10分钟刷新一个令牌。如果应用程序在后台运行15分钟,然后在前台运行时,计时器将启动。我没想到会这样。虽然计时器不再在后台运行,但什么也没发生。似乎所有未触发/未失效的计时器都被runloop强存储,并且在前景化时,如果
fireDate
被传递,那么它们就会立即被触发。那么,我可以安全地依靠一个
fireDate
获得通过,或者我应该存储一个日期并与之进行比较吗?代码的巨大和平,这将帮助我完成我的应用程序,THNX:)。一个小问题,通过“当应用程序在后台时,可能会调用此方法”,您会想到什么?我想用它在3小时内从服务器更新一次数据。有更好的方法吗?你的应用程序放到后台最多只能运行10分钟。从iOS 7开始,这10分钟可以是不相交的。您可能可以使用iOS7新的后台模式:后台传输用于大型上载/下载,或静默推送用于远程唤醒您的应用程序。此代码示例表明应用程序本身的前台/后台状态与主队列与全局队列问题之间存在混淆。不需要将计时器的调度分派到全局队列。只需在主队列上安排计时器,就像正常情况一样,而
beginBackgroundTaskWithExpirationHandler
将使应用程序保持几分钟的活动状态。@Rob我将让它启动180秒,而不必将其包装在
beginBackgroundTaskWithExpirationHandler
…您建议使用
beginBackgroundTaskWithExpirationHandler
的任何原因?您可能正在这样做当您运行附加到Xcode调试器的应用程序时,会发生此问题,这会更改应用程序的生命周期。在未连接到Xcode的情况下运行它(例如,退出Xcode并直接从设备上运行),您会发现应用程序挂起的速度要快得多(除非您执行此后台任务)。
- (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");
}