iOS:使应用程序像服务一样运行

在iOS中,我将如何指示操作系统保持我的应用程序运行,即使它不在前台?

  • Skype的
  • Viber的
  • Empatica
  • Zenly

还有更多的应用程序这样做。

基本上,iOS中没有服务types的应用程序或function。 即使是“后台”应用程序(UIBackgroundMode)也无法完全自由地运行,并且没有其他操作系统上的服务或守护进程等限制。

这里是关于后台执行和通知以及定时器等的情况

1)一个应用程序不能在后台执行,除非:

a)它要求操作系统有额外的时间来这样做。 这是使用beginBackgroundTaskWithExpirationHandler完成的。 苹果没有特意指定这个额外的时间,但实际上大概是10分钟。

b)一个应用程序有一个背景模式,模式是:voip,audio,位置,报价。 即使它有这些types之一,一个应用程序不能没有限制地执行。 本讨论的其余部分假设应用程序没有背景模式。 如果您尝试使用这些背景模式之一来使您的应用程序能够在后台运行,但是您的应用程序不能合法使用特定的function,那么您的应用程序将在app store提交时被拒绝(即,有一个UIBackgroundMode它必须是:一个VoIP应用程序,需要持续的位置更新,能够不断地在后台播放audio是一个基本function,或作为一个新的应用程序)。

2)当一个应用程序被暂停时,不能做任何事情直接唤醒自己。 它以前不能预定一个NSTimer,它不能使用像performSelector:afterDelay。 等等

该应用程序可以再次激活的唯一方式是,如果用户做了一些事情,使其活跃。 用户可以通过以下途径完成此操作:

a)直接从其图标启动应用程序

b)启动应用程序,以响应应用程序以前预定的本地通知。

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

d)其他一些:如URL启动,如果应用程序注册处理通过URL启动; 或者其注册能够处理某种types的内容。

如果应用程序在本地/远程通知触发时位于前台,则应用程序将直接收到该应用程序。

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

只有当用户select通知时,应用程序才会被激活并执行。

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

更新IOS 7

1)有一些新的背景模式,如背景获取(然而,你仍然不能以确定性的方式被操作系统唤醒)

2)现在有一个背景推送通知

3)开始BackgroundTaskWithExpirationHandler的时间从10分钟缩短到3分钟左右。

事情现在在iOS7中改变了,现在是testing版了

来自苹果的开发者门户 :

通过在iOS 7中采用新的多任务处理API,使您的应用程序的内容保持最新状态。新的服务允许您的应用程序在后台更新信息并下载内容,而不会不必要地耗尽电池。 更新可以在机会时间发生,并根据使用情况进行智能排定,所以您的应用程序可以在用户需要时在后台更新内容。

是的我们可以做到这一点,

创build一个私人字段来跟踪我们的状态:

UIBackgroundTaskIdentifier _bgTask; 

现在调用这个方法,像一个服务一样运行你的应用程序

 if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) {  _bgTask = UIBackgroundTaskInvalid;  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; } 

现在创build一个select器 –

 - (void) doBackground:(NSNotification *)aNotification {  UIApplication *app = [UIApplication sharedApplication];  if ([app respondsToSelector:@selector(beginBackgroundTaskWithExpirationHandler:)])  {   _bgTask = [app beginBackgroundTaskWithExpirationHandler:^   {     dispatch_async(dispatch_get_main_queue(), ^     {      if (_bgTask != UIBackgroundTaskInvalid)      {        [app endBackgroundTask:_bgTask];        _bgTask = UIBackgroundTaskInvalid;      }     });   }];  } } 

当你完成你的任务时,

 UIApplication *app = [UIApplication sharedApplication]; if ([app respondsToSelector:@selector(endBackgroundTask:)]) {  if (_bgTask != UIBackgroundTaskInvalid)  {   [app endBackgroundTask:_bgTask];   _bgTask = UIBackgroundTaskInvalid;  } }