完成处理程序不返回任何内容,即使它看起来像在单步执行时

Posted

技术标签:

【中文标题】完成处理程序不返回任何内容,即使它看起来像在单步执行时【英文标题】:completion handler not returning anything even though its looks like it is when stepping through it 【发布时间】:2018-03-13 18:17:42 【问题描述】:

这里是函数,它使用了 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()
    

我正在为它编写一个单元测试,但它似乎没有在完成块中,即使它命中了:strongSelf.onCompletion?(Result.success(dataResponse))

到目前为止,单元测试是这样的:

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!)

知道可能是什么问题吗?

【问题讨论】:

您是在测试实际连接还是在测试 Mock? 【参考方案1】:

你有一些问题。

    在数据任务的完成块中,您正在调用strongSelf.onCompletion?...,但onCompletionnil,所以它什么也不做。 您的getNetworkConnection 函数有一个您从不使用的completionHandler 参数。 您对getNetworkConnection 的调用取决于被调用的completionHandler

onCompletion 属性似乎没有意义。

在数据任务中,将对strongSelf.onCompletion?... 的调用替换为对completionHandler 参数的调用。

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()

【讨论】:

做得很好。非常感谢!

以上是关于完成处理程序不返回任何内容,即使它看起来像在单步执行时的主要内容,如果未能解决你的问题,请参考以下文章

GDB 调试多线程程序的总结

即使文件存在,readFileSync也不返回任何数据

VBA 在运行时崩溃,但在单步执行时工作

我的代码就像在一个while循环中一样,即使它不是

为啥在单步执行 ASP.NET MVC 控制器时,我的 VS2008 调试会话总是退出?

不理解此代码中的完成处理程序