Am unable to receive HTTP responses with UIViewController set as URLSessionDelegate

This question is also, here, one StackOverflow. But it's only gotten 8 views, and I am stuck till I find out what am I doing wrong.

I am able to create a URLSesion, build a request with a file to upload and successfully call it from my app. On my server side, the proper script is called, uploaded file is saved, etc,. However, I am not receiving the HTTP responses, data, etc.

Actually had this working without the delegate, when the HTTP response functions were within the task itself. But am now trying to expand functionality and am missing something while trying implement the delegate.

The trimmed code is below, and it all works, with the exception of setting up UIViewController as the URLSession delegate. Just trying to figure out why my UIViewController is not receiving the HTTP responses.

Below is the code for:

  1. UIViewController
  2. Class which creates the upload session (UploadService)
  3. Extension for UIViewController which I want to use to process the responses
  4. How the previous task looked, when it worked. Before I tried to implement the delegate.

UIViewController

class UploadInv : UIViewController {
    
    var xFile : XFile?

    ...create UI....

    let uploadService = UploadService()
    lazy var uploadSession: URLSession = {
    let configuration = URLSessionConfiguration.default
        return URLSession(configuration: configuration, delegate: self, delegateQueue: .main)
    }()

    override func viewWillAppear(_ animated: Bool) {
    ...
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        uploadService.uploadSession = uploadSession

    ... code the lays out all buttons, labels, etc...
    }

    @objc func buttonAction(sender: UIButton!) {
        guard let theButton = sender else { return}
        let myTag = theButton.tag
        
        switch myTag {
            //button to start upload  
            case ButtType.up.rawValue:
                uploadService.start(upFile: xFile!, script: "uploadOrig.pl", upLoadInvClass: self)
                uploadService.task?.resume()
            
            //button to select file to upload
            case ButtType.file.rawValue:
                ... file xFile with file info            
        }
    }

UploadService

class UploadService  {
    var task: URLSessionUploadTask?
    
    var uploadSession = URLSession.shared

    func start(upFile:  XFile, script: String, upLoadInvClass: UploadInv) {
        var request = upFile.makeUrlReq(upFile: upFile, script: script)
        
        self.task = uploadSession.uploadTask(with: request, from: request.httpBody! )
    }
}

extension

    extension UploadInv:  UIDocumentPickerDelegate, URLSessionDelegate {
        
        func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
            
     ... file xFile info for upload ....        
     ... http request created  ....             
        }
        
// Below are the three simple functions which I would handle 
// responses the server, but these never seem to get called.        

        func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
            if let err = error {
                print("Error: \(err.localizedDescription)")
            }
        }
        
        func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: (URLSession.ResponseDisposition) -> Void) {
                print("didReceive response")
                completionHandler(URLSession.ResponseDisposition.allow)
         }
         
         func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
           print("didReceive data")
             if let responseText = String(data: data, encoding: .utf8) {
                print(responseText)
             }
        }
    }

Pre-Delegate model which worked

class UploadService  {
    
    var uploadSession = URLSession.shared

    func start(upFile:  XFile, script: String, upLoadInvClass: UploadInv) {
        var request = upFile.makeUrlReq(upFile: upFile, script: script)
        
        uploadSession.uploadTask(with: request, from: request.httpBody  )
        { (data, response, error) in
            if let response = response {
               upLoadInvClass.upResp(resp: response)
            }
            
            if let error = error {
                upLoadInvClass.upErr(error: error)
            }
            
            if let data = data {
                upLoadInvClass.upData(data: data)

            }
            }.resume()
    }
}
Answered by Scott in 714051022

The error is subtle. But toss this line in somewhere such as viewDidLoad and the issue will reveal itself:

assert(uploadSession.delegate! is URLSessionDataDelegate)

Oh you.....I see what you did there. I'm going to start calling what you did "Passive/Aggressive teaching." And I mean that as a compliment. Thank you.

Accepted Answer

The error is subtle. But toss this line in somewhere such as viewDidLoad and the issue will reveal itself:

assert(uploadSession.delegate! is URLSessionDataDelegate)

For people following along: he implemented some URLSessionTaskDelegate and URLSessionDataDelegate methods in the view controller, but the URL session knew only that it claimed to be a URLSessionDelegate. The fix was to change this:

extension UploadInv: UIDocumentPickerDelegate, URLSessionDelegate {

...to this:

extension UploadInv: UIDocumentPickerDelegate, URLSessionDataDelegate {
Am unable to receive HTTP responses with UIViewController set as URLSessionDelegate
 
 
Q