【问题标题】:Background mode with NSTimers and server calls具有 NSTimers 和服务器调用的后台模式
【发布时间】:2016-01-19 21:53:08
【问题描述】:

我正在开发一个 sdk,它使用 NSTimer 在 x 分钟到期时进行服务器调用,并且服务器调用在完成一些工作后将计时器重置回 x 分钟。我遇到的问题是当我的应用程序在后台时我的计时器停止运行,并在我的应用程序回到前台时立即恢复。我如何让它发挥作用?

//initialize self.myTimer somewhere in my code
//called once somewhere in my code-->[self resetTimer:self.myTimer expiry:30];

- (void)resetTimer:(NSTimer *)timer expiry:(float)seconds {
[timer invalidate];
NSTimer *newTimer = [NSTimer timerWithTimeInterval:seconds
                                            target:self
                                          selector:@selector(updateTimer:)
                                          userInfo:nil
                                           repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:newTimer forMode:NSRunLoopCommonModes];

self.myTimer = newTimer;

}

- (void) updateTimer:(NSTimer *)timer {

    [timer invalidate];

    dispatch_queue_t queue = dispatch_queue_create("update", NULL);
    dispatch_async(queue, ^{
    [self serverCall];
    });
}

-(void)serverCall{
//make server call and do some work
[self resetTimer:self.myTimer expiry:30];


}

【问题讨论】:

    标签: ios objective-c nstimer background-process


    【解决方案1】:

    当应用处于后台时,计时器不会继续触发。如果您愿意让操作系统设置服务器调用的速度,您可以通过参考background execution doc 中的“机会性地获取少量内容”部分来完成此操作。

    要点是在 info.plist 中设置您应用的 UIBackgroundModes 键 == 获取。

    当 iOS 决定授予您的应用一些周期时,您可以在以下位置运行 short 任务:

    - (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
        [self serverCall];  // BUT! read on
    }
    

    但是你需要重构你的serverCall 来告诉调用者什么时候完成。否则,您将不知道何时调用completionHandler:

    - (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
        [self newServerCallWithCompletion:^(BOOL gotNewData) {
            UIBackgroundFetchResult result = (gotNewData)? UIBackgroundFetchResultNewData : UIBackgroundFetchResultNoData;
            completionHandler(result);
        }];
    }
    

    有关UIBackgroundFetchResult 的更多选项,请参阅文档。

    有了这个,iOS 将设置请求的速度,因此您将无法更频繁地发出请求,而不是当您的应用程序有机会时。通过保留最后一次请求的时间,您可以减少请求的频率。只需检查自上次请求以来的间隔是否为 <= 到某个所需的最大频率。如果是,只需使用“无数据”立即调用 completionHandler。

    【讨论】:

    • performFetchWithCompletionHandler 方法似乎只在应用委托中可用。我目前正在开发一个没有 appdelegate 的静态库。我可以将它添加到使用我的静态库的测试应用程序中,但这违背了拥有静态库的目的。当我在前台执行服务器调用并切换到允许我在我的应用程序在后台执行服务器调用的另一种方法时,我仍然想使用我的计时器。这可能吗?
    • 当然,计时器方法在前台很好用。但是在后台执行处理的唯一方法是通过应用程序委托中的钩子。要在库中执行此操作,您必须向库的客户安装说明提供配置 info.plist 并在应用程序委托中添加对库的调用。 (无论如何,您都希望图书馆的客户知道并批准后台处理)。
    • 如果我想在不同时间调用不同的服务器调用会发生什么?假设我有一个在 5 分钟时调用方法 A 的计时器 A 和在 10 分钟时调用方法 B 的计时器 B。计时器在前台工作正常,但是如何使用 performFetchWithCompletionHandler 在后台获取中设置等效项?
    • 在控制节奏之外,你可以在后台调用时做任何你想做的事情。因此,要在调用时获得不同的操作,而不是让计时器告诉你,坚持一个小状态,说明你上次做了什么或下次需要做什么。请记住快速运行并调用完成处理程序。
    猜你喜欢
    • 1970-01-01
    • 2012-02-15
    • 2011-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    • 2020-09-21
    相关资源
    最近更新 更多