21

我有一个需要将数据(使用 POST)发送到服务器的应用程序。此功能必须在 NavigationController 子控制器之一上,并且用户应该能够离开此控制器和/或关闭应用程序(仅支持 iPhone4/iOS4)。我应该使用线程/NSOperations 或/和使用现有的异步方法发送数据吗?任何想法/最佳实践如何实现这一点?

4

5 回答 5

31

好的,我会回答我自己的问题。首先,如tc所说,最好在应用程序委托上有这个调用,这样可以关闭NavigationController中的View。其次,标记后台处理的开始beginBackgroundTaskWithExpirationHandler:和结束,endBackgroundTask:如下所示:

。H:

UIBackgroundTaskIdentifier bgTask;

米:

- (void)sendPhoto:(UIImage *)image
{
  UIApplication *app = [UIApplication sharedApplication];

  bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
    [app endBackgroundTask:bgTask]; 
    bgTask = UIBackgroundTaskInvalid;
  }];


  NSLog(@"Sending picture...");

  // Init async NSURLConnection

  // ....
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

  NSLog(@"Picture sent.");
  
  UIApplication *app = [UIApplication sharedApplication];

  if (bgTask != UIBackgroundTaskInvalid) {
    [app endBackgroundTask:bgTask]; 
    bgTask = UIBackgroundTaskInvalid;
  }
}

在 iOS 终止您的应用程序之前,您有 10 分钟的时间。你可以检查这个时间[app backgroundTimeRemaining]

于 2010-10-15T12:16:44.910 回答
4

I'd just use NSURLConnection. It's a bit tricky if you want to send multipart/form-data (see the SimpleURLConnections/PostController.m example). I'd stick it in the app delegate, but I'm lazy like that.

You shouldn't worry about threads at all unless non-blocking I/O (i.e. NSURLConnection) is too slow. Threading has its own overheads, and inter-thread communication is a pain, and deadlocks are terrible.

What you do need to do is start a background task to allow your app to continue executing while backgrounded (end the background task in connectionDidFinishLoading: and connection:didFailWithError). Backgrounded apps are given about 10 minutes to finish executing background tasks.

于 2010-10-14T01:18:12.807 回答
1

使用 ASIHTTP 并设置队列。您需要的所有信息都可以在这里找到:

http://allseeing-i.com/ASIHTTPRequest/

这是完成您想要完成的任务的最简单方法。对于发送大量数据,最好在后台发送以保持 UI 响应。ASIHTTPRequest 提供了启动多个查询所需的所有方法(即进度检查、回调等)。

大量出色的 iPhone 应用程序都在使用它。

于 2010-10-14T00:16:41.537 回答
0

对于需要在用户执行其他操作时运行的任何长时间运行的进程,我肯定会建议使用第二个线程。

您需要考虑的另一件事是如果用户启动该过程然后点击主页按钮会发生什么。服务端交互被打断会如何影响?当用户下次进入应用程序时,它可以继续吗?等等

于 2010-10-13T23:31:47.360 回答
0

我想支持提到的帖子:

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
      [app endBackgroundTask:bgTask]; 

      bgTask = UIBackgroundTaskInvalid;
}];

但也要指出,您可能还希望将工作单元封装在 NSOperation 子类中。这将使其具有极强的可重用性,并且当与 NSOperationQueue 结合使用时,会自动处理线程等等。稍后,当您想要更改代码,或者让它出现在您的应用程序的不同位置时,移动或编辑将是微不足道的。

关于使用操作队列的一个注意事项是,在这种情况下,您实际上希望从队列中发送同步 url 请求。这将使您不必担心并发操作。这是您可能会发现有用的链接:

http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/

于 2010-10-15T20:02:46.643 回答