NSURLSession dataTaskWithURL

时间:2014-07-10 00:23:14

标签: multithreading asynchronous nsurlsession

我正在使用NSURLSession dataTaskWithURL:completionHandler。看起来,completionHandler是在一个线程中执行的,该线程与调用dataTaskWithURL的线程(在我的情况下,它是主线程)不同。所以我的问题是,因为它是异步的,主线程是否有可能退出,但是由于响应没有返回,所以completionHandler线程仍在运行,这是我试图避免的情况。如果发生这种情况,我该如何解决这个问题呢?顺便说一句,我正在构建这个框架,而不是应用程序。谢谢。

3 个答案:

答案 0 :(得分:1)

在您的问题的第一部分中,您似乎不确定完成处理程序是否在另一个线程上运行。要确认这一点,请查看NSURLSession Class Reference。如果我们看一下"创建一个会话"我们可以在描述中看到以下方法的答案。

+ sessionWithConfiguration:delegate:delegateQueue:

<强>夫特

init(configuration configuration: NSURLSessionConfiguration,
      delegate delegate: NSURLSessionDelegate?,
 delegateQueue queue: NSOperationQueue?)

<强>目标C

+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
                                  delegate:(id<NSURLSessionDelegate>)delegate
                             delegateQueue:(NSOperationQueue *)queue

在NSOperationQueue队列参数的参数表中,引用如下。

  

用于调度委托调用和完成处理程序的操作队列。队列不必是串行队列。如果为nil,则会话创建一个串行操作队列,用于执行所有委托方法调用和完成处理程序调用。

因此我们可以看到默认行为是提供队列,无论是来自开发人员还是作为默认的类行为。我们再次可以在方法+ sessionWithConfiguration:

的注释中看到这一点
  

<强>讨论

     

调用此方法相当于调用   sessionWithConfiguration:delegate:delegateQueue:带有nil委托   和队列。

如果您想了解更多信息,请阅读Apple的Concurrency Programming Guide。这对于理解Apple的一般线程方法也很有用。

因此- dataTaskWithURL:completionHandler:的完成处理程序在不同的队列上运行,队列通常提供自己的线程。这是您问题的主要组成部分。主线程可以退出,而完成处理程序仍在运行吗?

简明的答案是否定的,但为什么呢?

要回答这个问题,我们再次转向Apple的文档,以及每个人都应该在应用开发者职业生涯早期阅读的文档!

The App Programming Guide

  

主要运行循环

     

应用程序的主运行循环处理所有与用户相关的事件。该   UIApplication对象在启动时设置主运行循环并使用   它处理事件并处理基于视图的界面的更新。如   顾名思义,主运行循环在app的main上执行   线。此行为可确保处理与用户相关的事件   按顺序排列。

所有用户交互发生在主线程上 - 没有主线程,没有主运行循环,没有应用程序!因此,您提出的可能情况应该永远不存在!

Apple似乎更关心你在主线程上做背景工作。查看部分&#34;将工作移离主线程&#34; ...

  

请务必限制您在主线程上所做的工作类型   应用程序。主线程是您的应用处理触摸事件和其他事件的位置   用户输入。为确保您的应用始终对用户做出响应,   你永远不应该使用主线程来执行长时间运行或   可能无限制的任务,例如访问网络的任务。   相反,您应该始终将这些任务移到后台线程上。   这样做的首选方法是使用Grand Central Dispatch(GCD)或   NSOperation对象以异步方式执行任务。

我知道这个答案很长,但我觉得有必要在回答你的问题时提供洞察力和细节 - &#34;为什么&#34;同样重要,这是很好的评论:)。

答案 1 :(得分:0)

NSURLSessionTasks默认情况下总是在后台运行,这就是为什么我们有完成处理程序,当我们从Web服务获得响应时可以使用它。

如果您没有得到任何回复,请浏览您的请求网址以及HTTPHeaderFields是否设置正确。

粘贴您的代码,以便我们可以提供帮助

答案 2 :(得分:0)

我刚问了同样的问题。然后想出了答案。完成处理程序的线程在NSURLSession的init中设置。

来自documentation

init(configuration configuration: NSURLSessionConfiguration,
     delegate delegate: NSURLSessionDelegate?,
     delegateQueue queue: NSOperationQueue?)`
  

queue - 用于调度委托调用和完成处理程序的队列。如果为nil,则会话创建一个串行操作队列,用于执行所有委托方法调用和完成处理程序调用。*

我在主线程上设置完成的代码:

var session = NSURLSession(configuration: configuration, delegate:nil, delegateQueue:NSOperationQueue.mainQueue())

(在Swift中显示,Objective-C相同)如果没有解决,可能会发布更多代码。