Ios NSURLSessionTaskDelegate方法URLSession:task:DidCompleteWither错误:从未调用
我所有的网络代码都依赖于NSURLSession委托方法,而不是完成处理程序。我的数据和下载任务都很好,但我的上传任务从来不会导致Ios NSURLSessionTaskDelegate方法URLSession:task:DidCompleteWither错误:从未调用,ios,objective-c,nsurlsession,Ios,Objective C,Nsurlsession,我所有的网络代码都依赖于NSURLSession委托方法,而不是完成处理程序。我的数据和下载任务都很好,但我的上传任务从来不会导致 URLSession:task:didcompletewitheror:正在调用。但是, 调用URLSession:dataTask:didReceiveData:和URLSession:dataTask:willCacheResponse:completionHandler:委托方法 如果我在会话对象上将资源超时设置为一个非常低的值,则会调用didpletewit
URLSession:task:didcompletewitheror:
正在调用。但是,
调用URLSession:dataTask:didReceiveData:
和URLSession:dataTask:willCacheResponse:completionHandler:
委托方法
如果我在会话对象上将资源超时设置为一个非常低的值,则会调用didpletewitherrs
,但这显然不是一个解决方案
有什么想法吗?我快疯了
谢谢。如果实现了
willCacheResponse
,您将看不到调用了didcompletewitheror
,但是如果实现未能实际调用completionHandler
。您必须调用completionHandler
提供
completionHandler
参数(例如身份验证质询、重定向等)的任何和所有NSURLSession
委托方法也是如此。如果实现了这些方法,则必须确保调用了completionHandler
。Rob的回答是正确的,并给了我一个很大的线索。然而,对于我的具体问题,我没有意识到为什么不调用NSURLSessionTaskDelegate
方法。如果我可以提供另一个不同重点的答案
许多NSURLSession
任务创建方法有两种变体;一个带有completionHandler
参数,另一个没有
例如:
func dataTaskWithRequest(_ request: NSURLRequest) -> NSURLSessionDataTask
func dataTaskWithRequest(_ request: NSURLRequest, completionHandler completionHandler: (NSData?, NSURLResponse?, NSError?) -> Void) -> NSURLSessionDataTask
如果使用了completionHandler
方法,则将忽略任何委托方法(在本例中为NSURLSessionTaskDelegate
)。尽管在NSURLSession
initialiser中指定了一个委托,但仍然存在这种情况
下面的代码演示了这一点。切换任务
声明注释以查看是否调用了代理:
import UIKit
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
class MyDelegate:NSObject, NSURLSessionTaskDelegate
{
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
NSLog("Delegate called")
}
}
let myDel = MyDelegate()
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config, delegate: myDel, delegateQueue: NSOperationQueue())
let url = NSURL(string: "http://httpbin.org")
let request: NSURLRequest = NSURLRequest(URL: url!)
// With completionHandler, delegate method above NOT called
let task : NSURLSessionDataTask = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
NSLog("Task done")
})
// Without completionHandler, delegate method above IS called
//let task : NSURLSessionDataTask = session.dataTaskWithRequest(request)
task.resume()
TLDR:发疯想知道为什么不调用
NSURLSession
的委托方法?使用替代方法签名创建会话任务省略completionHandler参数的在这里展开另一个答案,将调用完成处理程序或委托方法的状态
与大多数网络API一样,NSURLSession API也是高度异步的。它以两种方式之一将数据返回到应用程序,具体取决于您调用的方法:
- 传输成功完成或出现错误时调用的完成处理程序块
- 通过在接收数据和传输完成时调用会话委托上的方法
我解决了这个问题,就像在
willCacheResponse
函数中添加completionHandler
一样
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse *__nullable cachedResponse))completionHandler {
NSLog(@"%s", __FUNCTION__);
completionHandler(proposedResponse);
}
在这种情况下,有人可能希望检查的另一种可能性是,您的URLSession委托方法没有标记为private。如果是,则不会调用这些方法。。。如果将修饰符保留在方法之外,然后在警告中使用“自动修复”来修复方法的修饰符(使其成为私有的),那么这很容易意外地做到 方法签名应为:
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
非常感谢。我知道一定是这样的小事。在发布我的问题后,我注意到我的一些数据和下载任务也遇到了同样的问题。我猜short&sweet单元测试并不总是遇到同样的问题,这实际上使它成为一个更糟糕的问题,而且(似乎)没有文档记录。在为苹果的文档辩护时,它说,“如果你的委托实现了这个方法,它必须调用这个完成处理程序”(原始文档中的重点)。如果不调用此
completionHandler
(更糟糕的是,文档描述了将导致泄漏,但忽略了承认可能出现的更广泛的问题),它无法准确地说明将发生什么,但在他们的辩护中,他们相当明确地表示必须调用完成处理程序。但是我感觉到了你的痛苦:我知道这个问题的唯一原因是我自己也经历过。完成处理程序块没有引用委托方法中使用的(NSURLSessionTask*)任务
参数。如果没有代理的任务
,如何从块内重试任务?顺便说一下,这个答案是正确的…`uploadTaskWithRequest:fromData:
点击委托方法,但uploadTaskWithRequest:fromData:completionHandler:
不点击。在我的情况下,即使我没有使用completionHandler方法,也不会调用委托回调。您好@mph您如何设置此任务委托?事实上,我正面临一些问题,而这些代表没有接到电话。或“open func”-今天这对我来说有点小意思,感谢你给出了“正确”的答案,尽管其他问题也是完全正确的。打倒代理模式@蛇油关于开放性是有效的,只是一些可以看到的东西!很高兴它能帮上忙,因为这让我困惑了一段时间!就是这样。编译器没有警告我它们需要公开。但奇怪的是,有些委托函数被调用了。