我的所有网络代码都依赖于NSURLSession委托方法 - 而不是完成处理程序。我的数据&下载任务一切都很好,但我的上传任务永远不会导致
URLSession:task:didCompleteWithError:
被召唤。然而
调用了URLSession:dataTask:didReceiveData:
和URLSession:dataTask:willCacheResponse:completionHandler:
委托方法 ARE 。
如果我在会话对象上将资源超时设置为非常低的值,则会调用didCompleteWithErrors
,但这显然不是解决方案。
有什么想法吗?我快要疯了。
感谢。
答案 0 :(得分:5)
如果您实施didCompleteWithError
,则不会看到willCacheResponse
,但如果实施无法实际调用completionHandler
。您必须致电completionHandler
。
任何和所有提供NSURLSession
参数的completionHandler
委托方法(例如身份验证质询,重定向等)也是如此。如果实现这些相应的方法,则必须确保调用completionHandler
。
答案 1 :(得分:2)
NSURLSessionTaskDelegate
方法。如果我可以被允许以不同的焦点提供另一个答案。
许多NSURLSession
任务创建方法有两种变体;一个completionHandler
参数,一个没有。
例如:
func dataTaskWithRequest(_ request: NSURLRequest) -> NSURLSessionDataTask
func dataTaskWithRequest(_ request: NSURLRequest, completionHandler completionHandler: (NSData?, NSURLResponse?, NSError?) -> Void) -> NSURLSessionDataTask
如果使用completionHandler
方法,则会忽略任何委托方法(在本例中为NSURLSessionTaskDelegate
。尽管已在NSURLSession
初始化程序中指定了委托,但仍然存在这种情况。
以下Playground代码演示了这一点。切换task
声明注释以查看是否调用了委托:
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参数的内容。
答案 2 :(得分:1)
在这种情况下,有人可能想要检查的另一种可能性是您的URLSession委托方法未标记为私有。如果是的话,这些方法将不会被调用...如果将修饰符置于方法之外,然后在警告上使用自动修复方法来固定方法的修饰符(将其设为私有),这很容易偶然发生。
方法签名应为:
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
答案 3 :(得分:0)
To expand upon another answer here, the NSURLSession docs state that either the completion handler or delegate methods will be called.
Like most networking APIs, the NSURLSession API is highly asynchronous. It returns data to your app in one of two ways, depending on the methods you call:
To a completion handler block that is called when a transfer finishes successfully or with an error.
By calling methods on the session’s delegate as data is received and when the transfer is complete.
A more specific ask of this question is here:
答案 4 :(得分:0)
如果您有completionHandler
功能,我就像在willCacheResponse
函数中添加- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse *__nullable cachedResponse))completionHandler {
NSLog(@"%s", __FUNCTION__);
completionHandler(proposedResponse);
}
一样解决了这个问题。
{{1}}