我一直在努力了解回调在Swift中是如何工作的。我已经看了很多例子(比如这一个),这些例子帮助我更好地理解了回调,但我在正确实现回调方面运气不佳。
我有一个函数,它接受URL,从web api下载一些XML数据,然后将其解析为对象。同时,我有一个UILabel,它正在等待来自XML请求的一些数据。
下面是我想用回调设置的函数的部分示例。为了清楚起见,假设它只返回一个数据点,该数据点稍后将分配给UILabel:
XMLUtility.swift
// global
var weekForecasts = [DayForecast]()
class XMLUtility {
func retrieveDataFromXML(myUrl: String) {
if let url = NSURL(string: myUrl) {
if let data = NSData(contentsOfURL: url) {
var error: NSError?
var cleanedData = filterData(data)
if let doc = AEXMLDocument(xmlData: cleanedData, error: &error) {
//... does some work parsing xml ////
for day in date {
//... some work assigning values /////
weekForecasts.append(thisDay)
}
}
}
}
问题出现在我的ViewController中。。。我有一些UILabels正在等待来自XML数据请求的值。加载ViewController时,XML尚未处理,标签无法接收值。
以下是我在ViewController中所做操作的简化示例:
ViewController.swift
@IBOutlet weak var currentTemperatureLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
currentTemperatureLabel.text = // I get a value out of my [DayForecasts]
}
我理解为什么会出现这种情况,而且我对如何解决问题有着新手般的理解。我认为我需要使用回调,但根据我迄今为止看到的示例,我不确定如何实现回调。
我的问题:
给定提供的示例,我将如何将retrieveDataFromXML
方法转换为回调。此外,我如何从ViewController调用函数来访问数据。
如有任何帮助,我们将不胜感激!
func retrieveDataFromXML(myUrl: String, completion: ((Array<DayForecast>) -> Void)) {
if let url = NSURL(string: myUrl) {
if let data = NSData(contentsOfURL: url) {
var error: NSError?
var cleanedData = filterData(data)
var weekForecasts = [DayForecast]() //local variable
if let doc = AEXMLDocument(xmlData: cleanedData, error: &error) {
//... does some work creating objects from xml
for day in date {
//... some work assigning values /////
weekForecasts.append(thisDay)
}
//pass the local array into the completion block, which takes
//Array<DayForecast> as its parameter
completion(weekForecasts)
}
}
}
}
称为类似
//in this example it is called in viewDidLoad
func viewDidLoad() {
var urlString = "urlstring"
retrieveDataFromXML(urlString, {(result) -> Void in
//result is weekForecasts
//UI elements can only be updated on the main thread, so get the main
//thread and update the UI element on that thread
dispatch_async(dispatch_get_main_queue(), {
self.currentTemperatureLabel.text = result[0] //or whatever index you want
return
})
})
}
这就是你的问题所要求的吗?