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;  } }