Reputation: 779
I use the following code to make a HTTP requests with URLSession and dataTask, but sometimes it gives me timeouts.
I just use the URLSessionDelegate to bypass the Authentication Server Trust in one of our development servers that uses HTTPS, if I use urlSession without delegate.
This error is completely inconsistent. Sometimes it works perfect, sometimes not.
Is it possible to validate the HTTP Server with the "URLCredential(trust: challenge.protectionSpace.serverTrust!" without using a delegate ?
func fetch(with url:String, completion: @escaping (Result<Data, Error>) -> Void) {
let request = URLSessionHelper.getRequestWithUrl(endpointUrl: url, httpMethod: HTTPMethod.get, jsonBodyData: nil)
weak var session = URLSession(configuration: URLSessionHelper.sessionConfiguration, delegate: SessionDelegate.shared, delegateQueue: nil)
session!.dataTask(with: request, completionHandler: {
data, response, error in
guard let data = data else {
print("nil data")
completion(.failure(NetworkError.timeout))
return
}
if error != nil {
print("nil error \(error!)")
completion(.failure(error!))
} else {
print("success")
completion(.success(data))
}
}).resume()
}
This is my SessionDelegate class
class SessionDelegate:NSObject, URLSessionDelegate
{
static var shared: SessionDelegate = {
let instance = SessionDelegate()
return instance
}()
//private override init() {}
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
// usado para fazer o bypass na autenticação self-signed do certificado do servidor
// We've got a URLAuthenticationChallenge - we simply trust the HTTPS server and we proceed
print("start didReceive challenge 1")
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
EDIT 1
If I use
UrlSession.shared.dataTask
with a secondary data server(that uses HTTP, not HTTPS) instead of using
weak var session = URLSession(configuration: URLSessionHelper.sessionConfiguration, delegate: SessionDelegate.shared, delegateQueue: nil
everything works fine. But our clients use the HTTPS server, because of that I need to figure out how to create a code that could be used with the HTTPS server without to be locked in the retain cycle that involves URLSession and the delegate.
EDIT 2
I modify the code:
let request = URLSessionHelper.getRequestWithUrl(endpointUrl: url, httpMethod: HTTPMethod.get, jsonBodyData: nil)
weak var session = URLSession(configuration: URLSessionHelper.sessionConfiguration, delegate: SessionDelegate.shared, delegateQueue: nil)
session!.dataTask(with: request, completionHandler: {
data, response, error in
guard let data = data else {
print("nil data")
completion(.failure(NetworkError.timeout))
session!.finishTasksAndInvalidate()
return
}
if error != nil {
print("nil error \(error!)")
completion(.failure(error!))
session!.finishTasksAndInvalidate() // invalidateAndCancel() or finishTasksAndInvalidate()
} else {
print("success")
completion(.success(data))
session!.finishTasksAndInvalidate()
}
}).resume()
but the problem still persists, if I restart the app and try to call URLSession, the problem appears for me.
If I use "invalidateAndCancel()" instead of "finishTasksAndInvalidate()", the behavior is the same.
Upvotes: 2
Views: 488
Reputation: 131398
In most classes that have a delegate, the delegate object is held weakly. URLSession
is an exception to that. If you look at the URLSession
docs, they say:
Important:
The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session. If you do not invalidate the session by calling the invalidateAndCancel() or finishTasksAndInvalidate() method, your app leaks memory until it exits.
So it sounds like your should call invalidateAndCancel()
or finishTasksAndInvalidate()
once you are done with your session. That would cause the session to release it's delegate.
Upvotes: 2