更新:
你可以使用信号量来冻结调用线程,直到任务返回一个值:参考
func performSynchronously(request: URLRequest) -> (data: Data?, response: URLResponse?, error: Error?) {
let semaphore = DispatchSemaphore(value: 0)
var data: Data?
var response: URLResponse?
var error: Error?
let task = self.dataTask(with: request) {
data = $0
response = $1
error = $2
semaphore.signal()
}
task.resume()
semaphore.wait()
return (data, response, error)
}
现在,假设我们想要在SwiftUI视图中呈现上述WWDCItemsLoader加载的项目。一个最初的想法是像这样做:
Ref
struct WWDCItemsList: View {
var loader: WWDCItemsLoader
@State private var loadingState = LoadingState<[WWDCItem]>.idle
var body: some View {
switch loadingState {
case .idle:
Color.clear.onAppear(perform: loadItems)
case .loading:
ProgressView()
case .loaded(let items):
List(items) { item in
...
}
case .failed(let error):
ErrorView(error: error, reloadHandler: loadItems)
}
}
private func loadItems() async {
loadingState = .loading
do {
let items = try await loader.load()
loadingState = .loaded(items)
} catch {
loadingState = .failed(error)
}
}
}
旧答案:(Swift 2.0)
当您使用完成处理程序时,请勿使用返回。
新答案: (Swift 2.0)
在使用完成处理程序时,不要使用return关键字。
func loadData(completion: @escaping (_ number: Int, _ strArr1: [String], _ strArr2: [String], _ strArr3: [String]) -> ()){
Alamofire.request(url!, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
switch(response.result) {
case .success(_):
if let JSON = response.result.value as! [[String : AnyObject]]!{
}
completion(number: numberRows, strArr1 : nameArray, strArr2 : ageArray, strArr3: birthdayArray)
break
case .failure(_):
print("Error")
completion(number: numberRows, strArr1 : nameArray, strArr2 : ageArray, strArr3: birthdayArray)
break
}
}
}
loadData (completion: { (number, strArr1, strArr2, strArr3) in
self.number = number
self.strArr1 = strArr1
})
如果您想在闭包中返回任何值,您必须使用完成处理程序来返回任何值或类似的内容,例如,如果您想返回布尔值:
func loadData(completion:(number: numberRows, strArr1 : nameArray, strArr2 : ageArray, strArr3: birthdayArray) -> (Bool))
在loadData
中
loadData( completion: { ( number, strArr1, strArr2, strArr3 ) -> (Bool) in
# code
return False
})
还是其他什么。
我使用的是Swift 3。但如果你想要另一个版本的Swift,请注意外部参数名和内部参数名,例如:@escaping (_ number: Int, _ strArr1: [String], _ strArr2: [String], _ strArr3: [String]) -> ())
如果您想设置外部参数名,只需要删除_
并为参数设置名称即可。