Swift 使用完成处理程序和 DispatchSemaphore 的异步请求

async requests on Swift using completion handler and DispatchSemaphore

我正在尝试使用 Alamofire's completion handlerDispatchSemaphores 在 Swift 上发出 async 请求。我需要得到一个响应然后 return 它到另一个方法,所以基本上这是我的代码

func customRequest(zipCode: String) -> Bool{
    var response = false

    let dispatchQueueProcess = DispatchQueue.global(qos: .userInitiated)
    let semaphore = DispatchSemaphore(value: 1)
    
    dispatchQueueProcess.async {
        
        semaphore.wait()

        apiRequest(zipCode: zipCode) { apiResponse in
        
            if apiResponse != nil {
            
response = apiResponse
               
             
            } else {
                print("Server did not Response")
            }
            
            semaphore.signal()
            
            
        }
    }
    
    return response
}

问题是请求总是 returns false 因为没有等到 apiRequest 响应...你有什么办法解决这个问题吗?非常感谢!

Ps。 apiRequest returns“真”/“假”

你的 return 语句在完成处理程序之外,所以它会立即 运行,returning 它的初始 false 值,而不是 returning 的结果根据您的要求提出要求。

您应该删除响应 属性 并在完成处理程序中处理响应。

您的目的是创建一个同步函数,它将阻塞并等待异步请求完成吗?

如果是这样,您就快完成了,但是您需要将信号量更改为以 0 而不是 1 开头(从 1 递减到 0 不会停止执行,它需要变为负数),并且您需要将 wait() 调用移到闭包之外,否则您不会阻止函数返回,而是会阻止您的闭包完成。

func customRequest(zipCode: String) -> Bool {
    var response = false
    
    let dispatchQueueProcess = DispatchQueue.global(qos: .userInitiated)
    let semaphore = DispatchSemaphore(value: 0)
    
    // Start async work on background thread, current function's thread 
    // execution point will then immediately move to the line 
    // after the closing brace 
    dispatchQueueProcess.async {
        apiRequest(zipCode: zipCode) { apiResponse in
            if let apiResponse = apiResponse {
                response = apiResponse
            } else {
                print("Server did not Response")
            }

            // Tell the original function's thread that it is OK to continue
            semaphore.signal()

        }
    }

    // Immediately wait for the semaphore after starting the async work so that
    // the customRequest(zipCode:) function pauses here until the semaphore is
    // signalled in the closure.
    semaphore.wait()
    
    // Once the semaphore.signal() call happens in the async closure execution
    // resumes, and the response variable can now be returned with the updated
    // value.
    return response
}

您可能会发现您实际上并不想创建这样的同步函数,因为如果您从主队列调用它,您将冻结 UI 直到收到响应。

编辑:此示例应在 Playground

中复制粘贴 运行
import Foundation

// template function to simulate the API call
func apiRequest(zipCode: String, response: (Bool?)->Void) {
    sleep(3)
    response(true)
}

func customRequest(zipCode: String) -> Bool{
    var response = false
    
    let dispatchQueueProcess = DispatchQueue.global(qos: .userInitiated)
    let semaphore = DispatchSemaphore(value: 0)
    
    dispatchQueueProcess.async {
        apiRequest(zipCode: zipCode) { apiResponse in
            if let apiResponse = apiResponse {
                response = apiResponse
            } else {
                print("Server did not Response")
            }
            semaphore.signal()

        }
    }
    
    semaphore.wait()
    
    return response
}

print("Result: \(customRequest(zipCode: "90030"))")