不会通过MultipartFormData调用encodingC

不会通过MultipartFormData调用encodingC

本文介绍了当主线程等待其运行时,Alamofire永远不会通过MultipartFormData调用encodingCompletion进行上传的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这种形式的代码:

func myFunction(<...>, completionHandler: (ResponseType) -> Void) {
    <prepare parameters>

    mySessionManager.upload(multipartFormData: someClosure,
        to: saveUrl, method: .post, headers: headers) { encodingResult in
          // encodingCompletion
          switch encodingResult {
                case .failure(let err):
                    completionHandler(.error(err))
                case .success(let request, _, _):
                    request.response(queue: self.asyncQueue) { response in
                        // upload completion
                        <extract result>
                        completionHandler(.success(result))
                    }
            }
     }
}

并测试如下代码:

func testMyFunction() {
    <prepare parameters>

    var error: Error? = nil
    var result: MyResultType? = nil

    let sem = DispatchSemaphore(value: 0)
    var ran = false
    myFunction(<...>) { response in
        if ran {
            error = "ran twice"
            return
        }
        defer {
            ran = true
            sem.signal()
        }

        switch response {
            case .error(let err): error = err
            case .success(let res): result = res
        }
    }
    sem.wait()

    XCTAssertNil(error, "Did not want to see this error: \(error!)")

    <test response>
}

我使用信号量来阻塞主线程,直到请求被异步处理为止;这对于我所有其他Alamofire要求都很有效-但不是这个要求。测试挂起。

(请注意,使用不会改变。)

I use a semaphore to block the main thread until the request is processed asynchronously; this works fine for all my other Alamofire requests -- but not this one. The test hangs.
(Note bene: Using active waiting does not change things.)

使用调试器,我发现


  • 所有执行的代码都很好,但是


  • all code that executes does so just fine but
  • encodingCompletion is never called.

现在,我最好的猜测是 DispatchQueue.main.async 说:在有时间的时候在主线程上执行此操作 –它永远不会,因为我的测试代码在那儿阻塞了(无论如何都会运行进一步的测试)。

Now my best guess is that DispatchQueue.main.async says, "execute this on the main thread when it has time" -- which it never will, since my test code is blocking there (and will run further tests, anyway).

我将其替换为 self.queue.async upload.delegate.queue.addOperation ,这是在同一函数中发现的另外两个排队操作。然后测试通过,但会产生意外错误;我的猜测是,然后 encodingCompletion 被称为太早了

I replaced it with self.queue.async and upload.delegate.queue.addOperation, two other queueing operations found in the same function. Then the test runs through but yields unexpected errors; my guess is that then, encodingCompletion is called too early.

有几个这里要问的问题;任何问题的答案都可以解决我的问题。

There are several questions to ask here; an answer to any can solve my problem.


  1. 我可以以不同的方式测试此类代码,以使 DispatchQueue.main 可以执行其他任务吗?

  2. 如何使用调试器找出哪个线程在何时运行?

  3. 如何使用适应不需要主队列?

  1. Can I test such code differently so that DispatchQueue.main can get to other tasks?
  2. How can I use the debugger to find out which thread runs when?
  3. How can I adapt Alamofire at the critical position so that it does not require the main queue?


推荐答案

我们不应该阻塞主线程。 XCTest有自己的等待异步计算的解决方案:

We should not block the main thread. XCTest has its own solution for waiting on asynchronous computations:

let expectation = self.expectation(description: "Operation should finish.")
operation(...) { response in
    ...
    expectation.fulfill()
}
waitForExpectations(timeout: self.timeout)

来自:






在XCTest之外,我们可以使用与可以:

var done = false
operation(...) { response in
    ...
    done = true
}

repeat {
    RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))
} while !done

注意:假设操作将其工作发送到同一队列上。如果它使用另一个队列,将无法使用;但是使用 DispatchSemaphore 的方法(请参阅)不会导致死锁并可以使用。

Note: This assumes that operation sends its work to the same queue itself is executed on. If it uses another queue, this won't work; but then the approach using DispatchSemaphore (see the question) does not cause a deadlock and can be used.

XCTest中的实现做得更多(期望值高,超时,可配置的睡眠间隔等),但这是基本机制

The implementation in XCTest does a lot more (multiple expectations, timeout, configurable sleep interval, etc.) but this is the basic mechanism.

这篇关于当主线程等待其运行时,Alamofire永远不会通过MultipartFormData调用encodingCompletion进行上传的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-21 01:30