我正在构建一个计算内容的应用程序。
用户将在OperationViewController
输入他/她的输入,然后他/她将点击“计算”。计算结果后,执行segue以显示ResultsViewController
。
有些计算需要很长时间,所以我认为它们应该在后台线程中完成。我应该显示一条消息,说它正在计算和活动指标。
我还从某个地方获取了一些代码,这些代码使得在后台运行的东西非常好。这是代码:
import Foundation
infix operator ~> {}
/**
Executes the lefthand closure on a background thread and,
upon completion, the righthand closure on the main thread.
Passes the background closure's output, if any, to the main closure.
*/
func ~> <R> (
backgroundClosure: () -> R,
mainClosure: (result: R) -> ())
{
dispatch_async(queue) {
let result = backgroundClosure()
dispatch_async(dispatch_get_main_queue(), {
mainClosure(result: result)
})
}
}
/** Serial dispatch queue used by the ~> operator. */
private let queue = dispatch_queue_create("serial-worker", DISPATCH_QUEUE_SERIAL)
然后,出现了问题。
在OperationViewController
中,有一种名为getResults
的方法:
private func getResults () -> [(name: String, from: String, result: String)]? {
// irrelevent code about getting the user's inputs from UITextFields
return operation.calculate(input) // This will take a few seconds
}
calculate
方法需要几秒钟才能返回。
前面提到的计算按钮有一个连接到ResultsViewController
的segue。我没有明确地致电performSegueWithIdentifier
。我只是控制将按钮拖到结果视图控制器。
在prepareForSegue
,我致电getResults
:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showOperationHelp" {
// irrelevent
} else if segue.identifier == "showResults" {
let vc = segue.destinationViewController as! ResultsViewController
vc.results = getResults()
}
}
现在我尝试将getResults
部分放在后台线程中:
} else if segue.identifier == "showResults" {
let vc = segue.destinationViewController as! ResultsViewController;
{ self.getResults() } ~> { vc.results = $0 };
}
但这不起作用,因为prepareForSegue
在计算完成之前返回。这意味着vc.results
返回时nil
为prepareForSegue
。这将导致ResultsViewController
不显示任何内容。
我尝试的另一种方法是在getResults
中将“do in background”放入其中:
private func getResults () -> [(name: String, from: String, result: String)]? {
// irrelevent code about getting the user's inputs from UITextFields
var results: [(name: String, from: String, result: String)]?;
{ self.operation.calculate(input) } ~> { results = $0 };
return results
}
同样,getResults
只会返回nil
。
当我编写C#时,我可以使用async/await
关键字来实现此目的。
我可以做类似的事情:
var results = await operations.Calculate(input);
当执行到达await
时,它会暂停并允许UI线程继续运行。异步操作完成后,执行将返回到已停止的位置并继续。
问题:我可以在Swift中执行上述操作吗?如果我不能,我怎么能等到计算完成并显示ResultsViewController
?
万一你不理解我,我会准确描述我想要的东西:
ResultsViewController
经过一番尝试,我只能得到这个:
ResultsViewController
,但没有结果ResultsViewController
不知道。P.S。我不知道如何改进问题标题......
答案 0 :(得分:2)
为了清晰起见,编辑原始回复:
让compute按钮调用一个名为calculate()的方法或显示活动指示符的方法,然后调用getResults方法。
给getResults()一个completionHandler,并在成功完成时关闭活动指示符并用完成的计算执行segue。