0

我正在尝试使用andasync对 Swift 提出请求。我需要得到响应,然后将其返回给另一个方法,所以基本上这是我的代码Alamofire's completion handlerDispatchSemaphores

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
}

问题是请求总是返回false,因为没有等到apiRequest响应......你有什么想法来解决这个问题吗?太感谢了!

附言。apiRequest返回“真”/“假”

4

2 回答 2

1

您的 return 语句在完成处理程序之外,因此它将立即运行,返回它的初始 false 值,而不是按照您的要求返回请求的结果。

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

于 2021-01-06T01:44:26.087 回答
1

您是否打算在这里创建一个同步函数,该函数将阻塞并等待异步请求完成?

如果是这样,您就快到了,但是您需要将 Semaphore 更改为从 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,直到收到响应。

编辑:这个例子应该复制粘贴在操场上运行

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"))")
于 2021-01-06T02:24:38.607 回答