关闭iPhone应用程序时发送网络消息

时间:2010-01-07 21:04:19

标签: iphone network-programming

我的iPhone应用程序支持使用CocoaAsyncSocket库的专有网络协议。当我的iPhone应用程序关闭时,我需要能够发送网络消息。发送消息的代码是从应用程序委托调用的,但应用程序在消息实际消失之前关闭。有没有办法让应用程序保持足够长的时间才能使消息消失?

布鲁斯

3 个答案:

答案 0 :(得分:2)

来自Apple的文档没有明确说明这一点,但我从网上看到的感觉以及从个人经验中获得的感觉是,在用户点击主页按钮关闭您的应用之后大约4到5秒应用程序实际终止。 iPhone操作系统正在控制此操作,因此您无法阻止终止以允许程序首先完成。基本上,当你的时间到了,你的程序就会被杀死。

但可能还有另一种解决方案。首先,我确认您的代码运行时间超过5秒。也许你可以让它运行以响应按钮点击,并计算它运行的时间。如果超过5秒,您可能会遇到这个超时问题。

然后,您可能会找到一种方法来触发从始终运行的服务器发送的消息。您应该有足够的时间来触发远程操作,然后可以在需要运行时执行。

或许您可以在退出时将重要信息保存到iPhone文件系统,并在下次有人启动应用程序时发送该消息,这理论上应该给您足够的时间。

希望这有帮助!

答案 1 :(得分:2)

我假设你已经从你的AppDelegate中调用它了:

- (void)applicationWillTerminate:(UIApplication *)application

但是,正如您所发现的那样,无法保证它会被调用或将被允许完成。根据您的尝试,有一些选项可能会或可能不会起作用:

  • 如果您需要服务器执行某种类型的清理操作,当客户端应用程序消失时,您可以尝试在服务器上查看TCP套接字关闭并将其视为触发事件。但是如果您明确需要使用闭包发回数据,则可能无效。

  • 如果您发回的数据不是时间敏感的,那么您可以像大多数分析库那样做并在客户端缓存数据(以及uuid)然后尝试在app上发送它关闭。如果它通过,您可以清除缓存(或在下次运行应用程序时执行此操作)。如果没有,它会被保存,您可以在下次运行应用程序时发送出去。在服务器上,您将使用uuid来避免重复请求。

  • 如果材料是时间敏感的,那么最好的办法是实施心跳并将定期更新的值发送到服务器。然后,当客户端应用程序死亡时,服务器超时心跳,并可以使用最后收到的值作为数据的最终结束点。

在任何一种情况下,如果您的自定义协议需要显式关闭事件,那么您可能需要重新考虑在现实生活中的移动环境中使用它,在这种环境中,事情必须更加流畅且容忍失败。

答案 2 :(得分:0)

正如其他人所说,没有办法绝对肯定你能够发送这个,但有一些方法可以提供帮助。

正如肯所说,你实际上在“willTerminate”和强制终止之间需要几秒钟,所以通常有时间做你需要的。

你几乎可以肯定遇到的问题是CocoaAsyncSocket。当您收到“willTerminate”消息时,您正处于主线程的最后一个运行循环中。因此,如果您阻止主线程,并且CocoaAsyncSocket正在主线程上运行,它将永远不会被处理。我记得,CocoaAsyncSocket实际上不会发送所有数据,直到下一个事件循环。

因此,一种方法是自己继续抽取事件循环:

- (void)applicationWillTerminate:(UIApplication *)application
{
     // ...Send your message with CocoaAsyncSocket...

     while (! ...test to see if it sent...)
     {
         [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
     }
}

我还看过将这项工作放到后台线程并让主线程终止,理论上让我们回到Springboard,同时继续运行几秒钟。我不能立即清楚使用NSThread(它是分离的)是否能正常工作。使用POSIX线程(默认情况下可以连接)可能有效,但可能会绕过后台线程的任何优点。无论如何,如果有用的话,可以看一下。在我的应用程序中,我们使用了“下次启动时发布”的方法,因为它始终有效(即使您崩溃了)。