1

For client certificate authentication I've to use URLSessionDelegate in the custom class for handling all requests. The problem is the class is not deinitialize after a request made.

Code:

class Request: NSObject, URLSessionDelegate, URLSessionTaskDelegate{
    
    
    func request(){
        
        let url:URL = URL(string: "https://stackoverflow.com")!
        
        let config = URLSessionConfiguration.default
        
        
        
        URLSession(configuration: config, delegate: self, delegateQueue: .main).dataTask(with: url) { (data, response, error) in
            
            print("Received")
            
        }.resume()
    }
    
    func request2(){
        
        let url:URL = URL(string: "https://stackoverflow.com")!
        
        let config = URLSessionConfiguration.default
        
        
        URLSession(configuration: config).dataTask(with: url) { (data, response, error) in
            
            print("Received")
            
        }.resume()
    }
    
    deinit {
        print("Class deinit...")
    }
}

When calling Request().request() then deinit is not called. Calling Request().request2() then deinit is called.

I am not sure how to resolve this problem. Please help me to find out the solution. Thank you...

2 Answers2

1

URLSession keeps a strong reference to its delegate (self in your case). Check the official documentation:

The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session. If you don’t invalidate the session, your app leaks memory until the app terminates.

You can invalidate the session using its methods finishTasksAndInvalidate() or invalidateAndCancel(). After that URLSession will release the strong reference to its delegate.

I guess you code example is just to demonstrate the behavior, but anyway I have to mention it's not a good practice to create a new URLSession for every single URLRequest.

alexander.cpp
  • 747
  • 6
  • 15
  • Thank you for the explanation. not a good practice to create a new URLSession is new to me. Yeah that make sense. Thank you! –  Aug 21 '21 at 23:48
  • 1
    If you use this URLSession very rarely, it's acceptable to create, use, and forget about it (as you do in this code example). But if you send such requests regularly, it's better to create once and reuse the session if possible. Discussion about this: https://stackoverflow.com/questions/52591866/whats-the-correct-usage-of-urlsession-create-new-one-or-reuse-same-one – alexander.cpp Aug 22 '21 at 00:00
-1

In request() when assigning self to the delegate you are creating a strong reference to the instance of the class. This causes a retention cycle and stops the instance being deinitialised. The answer is to weekly capture the delegate:

URLSession(configuration: config, delegate: self, delegateQueue: .main).dataTask(with: url) { [weak self] (data, response, error) in
            
            print("Received")
            
        }.resume()

In request2() without a delegate this obviously isn't happening.

There are numerous blogs and tutorials about this, so rather than repeating them all I'll let you google for the detail about capture list and strong and weak references :-)

flanker
  • 3,840
  • 1
  • 12
  • 20
  • Thank you very much!. I tried your solution but it's still not working. `deinit` is not called. –  Aug 21 '21 at 23:43
  • 1
    Sorry - did that without thinking and jumped to standard boilerplate, and it's wrong! The reason is right but the solution to releasing 'self' is wrong! @alexander.cpp has put in the correct solution, so I'll not edit. – flanker Aug 21 '21 at 23:50