Search code examples
iosswiftswift4operationcompletionhandler

completion handler not returning anything even though its looks like it is when stepping through it


Here is the function, its using Operation(NSOperation):

    typealias ResultType = Result<Data>
    typealias CompletionType = (ResultType) -> ()
    public var onCompletion: CompletionType?

  internal func getNetworkConnection(urlRequest: URLRequest, completionHandler: @escaping CompletionType)  {

        let task = self.urlSession.dataTask(with: urlRequest, completionHandler: { [weak self] (data, response, error) in
            guard let strongSelf = self else {
                return
            }

            if let errorResponse = error {
                //strongSelf.result = Result.failure(errorResponse)

                     strongSelf.onCompletion?(Result.failure(errorResponse))

            }

             if let responseFromServer = response as? HTTPURLResponse,
                200...299 ~= responseFromServer.statusCode{

                if let dataResponse = data{
                    //strongSelf.result = Result.success(dataResponse)


                    strongSelf.onCompletion?(Result.success(dataResponse))//it hits this point 


                } else {
                    strongSelf.onCompletion?(Result.failure(NSError()))
                }
             }

            strongSelf.urlSession.invalidateAndCancel()
        })

        task.resume()
    }

I'm writing a unit test for it but it appears nothing is in completion block even though its hit the: strongSelf.onCompletion?(Result.success(dataResponse))

Here's what the unit test looks like so far:

func test_getNetworkConnection(){

    let promise = expectation(description: "Completion handler invoked")

  sut?.getNetworkConnection(urlRequest: URLRequest(url: requestURL), completionHandler: { (data) in

        print(data) //never prints

        promise.fulfill()
    })

    wait(for: [promise], timeout: 100, enforceOrder: true)//exaggerated timeout but it fails
  //  XCTAssertTrue(returnedResponse!)
}

Any idea what may be the issue?


Solution

  • You have a few issues.

    1. Inside the completion block of the data task, you are calling strongSelf.onCompletion?... but onCompletion is nil so it doesn't do anything.
    2. Your getNetworkConnection function has a completionHandler parameter that you never use.
    3. Your call to getNetworkConnection is depending on the completionHandler being called.

    There seems to be no point to the onCompletion property.

    Inside the data task, replace calls to strongSelf.onCompletion?... with calls to the completionHandler parameter.

    typealias ResultType = Result<Data>
    typealias CompletionType = (ResultType) -> ()
    
    internal func getNetworkConnection(urlRequest: URLRequest, completionHandler: @escaping CompletionType)  {
        let task = self.urlSession.dataTask(with: urlRequest, completionHandler: { [weak self] (data, response, error) in
            guard let strongSelf = self else {
                return
            }
    
            if let errorResponse = error {
                completionHandler(Result.failure(errorResponse))
            }
    
            if let responseFromServer = response as? HTTPURLResponse,
                200...299 ~= responseFromServer.statusCode{
    
                if let dataResponse = data{
                    completionHandler(Result.success(dataResponse))
                } else {
                    completionHandler(Result.failure(NSError()))
                }
            } else {
                // TODO - need to call completionHandler here too
            }
    
            strongSelf.urlSession.invalidateAndCancel()
        })
    
        task.resume()
    }