Description:
I'm noticing that when using the completion handler variant of URLSession.dataTask(with:),
the delegate method urlSession(_:dataTask:didReceive:)
is not called—even though a delegate is set when creating the session.
Here's a minimal reproducible example:
✅ Case where delegate method is called:
class CustomSessionDelegate: NSObject, URLSessionDataDelegate {
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
print("✅ Delegate method called: Data received")
}
}
let delegate = CustomSessionDelegate()
let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
let request = URLRequest(url: URL(string: "https://httpbin.org/get")!)
let task = session.dataTask(with: request) // ✅ No completion handler
task.resume()
In this case, the delegate method didReceive is called as expected.
❌ Case where delegate method is NOT called:
class CustomSessionDelegate: NSObject, URLSessionDataDelegate {
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
print("❌ Delegate method NOT called")
}
}
let delegate = CustomSessionDelegate()
let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
let request = URLRequest(url: URL(string: "https://httpbin.org/get")!)
let task = session.dataTask(with: request) { data, response, error in
print("Completion handler called")
}
task.resume()
Here, the completion handler is executed, but the delegate method didReceive
is never called.
Notes: I’ve verified this behavior on iOS 16, 17, and 18.
Other delegate methods such as urlSession(_:task:didFinishCollecting:) do
get called with the completion handler API.
This happens regardless of whether swizzling or instrumentation is involved — the issue is reproducible even with direct method implementations.
Questions:
- Is this the expected behavior (i.e., delegate methods like didReceive are skipped when a completion handler is used)?
- If yes, is there any official documentation that explains this?
- Is there a recommended way to ensure delegate methods are invoked, even when using completion handler APIs?
Thanks in advance!
As I understand the documentation, this is indeed the expected behavior:
By using the completion handler, the task bypasses calls to delegate methods for response and data delivery, and instead provides any resulting NSData, URLResponse, and NSError objects inside the completion handler.