27

这个应用程序背后的想法很简单:下载一个文件。但是,此应用程序适用于并不总是在互联网访问范围内的人,因此我需要它知道在上午 9:00 时将文件下载到硬盘驱动器。应用程序中也会有一个按钮可以手动完成,但我已经开始工作了。

据我了解,即使有可能,这也将很困难。我知道 iOS 不喜欢多任务处理,但我也知道它确实允许后台计时器功能。我愿意接受任何人可能必须完成此任务的任何建议,即使这意味着编写一个单独的应用程序。谢谢。

编辑:我看到有可能使用通知,甚至可能是日历。该类别的想法也受到欢迎。

编辑 2:我还阅读了一些关于启动应用程序的外部服务器的内容,但没有给出描述。

4

5 回答 5

30

这是与应用程序安排某些活动定期发生有关的后台执行以及通知和计时器等的情况。

  1. 应用程序无法在后台执行,除非:

    1. 它要求操作系统提供额外的时间来执行此操作。这是使用beginBackgroundTaskWithExpirationHandler. Apple 没有(有意)指定这个额外的时间有多长,但实际上它大约是 10 分钟。

    2. 一个应用程序有一个后台模式,模式是:voip、音频、位置、报摊。即使它具有其中一种类型,应用程序也无法在没有某些限制的情况下执行。本讨论的其余部分假设应用程序没有后台模式。

  2. 当一个应用程序被暂停时,它不能做任何事情来直接唤醒自己。它以前不能安排一个 NSTimer,它不能使用像 performSelector:afterDelay 这样的东西。等等

    应用程序可以再次激活的唯一方法是用户执行某些操作使其激活。用户可以通过以下方式执行此操作:

    1. 直接从其图标启动应用程序

    2. 启动应用程序以响应应用程序先前在其处于活动状态时安排的本地通知。

    3. 启动应用程序以响应服务器发送的远程通知。

    4. 其他一些:例如,如果应用程序注册为处理通过 url 启动,则 URL 启动;或者如果它注册为能够处理某种类型的内容。

如果本地/远程通知触发时应用程序处于前台,则应用程序直接接收它。

如果在本地/远程通知触发时应用程序当前不在前台,则应用程序不会收到它。通知触发时没有执行任何代码!

只有当用户选择通知时,应用才会激活并且可以执行。

请注意,用户可以为整个设备或仅针对特定应用程序禁用通知,在这种情况下,用户将永远看不到它们。如果在通知即将触发时关闭设备,则它会丢失。

于 2012-06-05T20:07:41.947 回答
2

您可以使用本地通知。当用户打开显示的通知时,它们会执行代码。您可以将本地通知设置为以指定的时间间隔(例如每天、每小时、每周等)重复。这仍然需要用户打开应用程序才能开始该过程。

UILocalNotification 类参考

一旦委托方法触发,您只有几秒钟的时间来执行代码。注册一个长时间运行的后台任务,然后下载你需要做的任何事情。如果它不能在你为任务获得的 10 分钟内完成下载,那么你需要重新考虑你的下载策略。

Apple 多任务处理和后台处理

我们在我工作的 iOS 应用程序上使用了相同的概念,因此如果您设置正确,这将起作用。

更新

对于那些好奇这将如何工作的人,您只需要实现 UILocalNotification 委托方法。它们继承自应该已经存在的 UIApplicationDelegate。

-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
// start your long running bg task here and update your file

}

** 更新 2 **

Martin H 的回答是迄今为止最正确的。但这引出了一个问题,如果用户从不打开应用程序,那么下载他们永远不会看到的数据有什么意义呢?提醒他们打开应用程序和更新的重复本地通知可能是最好的方式,但如果用户希望它保持最新和最新,仍然需要用户与您的应用程序进行交互。

于 2012-06-05T19:49:35.017 回答
0

后台应用程序有一个固定的时间限制(我相信 10 分钟,但不要引用我的话,它可能会更少)来完成他们正在处理的任何事情。您将无法使用后台任务来做您想做的事。

您可以做的是使用上次下载的日期设置 NSUserDefault。在启动时检查保存的日期,如果日期不是当前日期,并且是在上午 9:00 之后,则以编程方式启动下载。

于 2012-06-05T19:31:50.037 回答
0

我很确定这是不可能的,您最多可以做的是向用户发送推送通知,以便他们在需要时手动更新。

于 2012-06-05T19:36:39.800 回答
-2

您是否尝试过以下操作?

if ([[[UIDevice currentDevice] systemVersion] floatValue] >=7.0)
    [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:600];


- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    completionHandler(UIBackgroundFetchResultNewData);
}
于 2014-12-30T10:37:06.687 回答