我编写了一个应该返回一个值的函数,但该值来自一个闭包。问题是如果我尝试从闭包内部返回一个值,它会将其视为完成处理程序的返回值。
private func loadData() throws -> [Item] {
var items = [Item]()
let jsonUrl = "http://api.openweathermap.org/data/2.5/forecast/daily?units=metric&cnt=7&q=coventry,uk"
print(jsonUrl)
let session = NSURLSession.sharedSession()
guard let shotsUrl = NSURL(string: jsonUrl) else {
throw JSONError.InvalidURL(jsonUrl)
}
session.dataTaskWithURL(shotsUrl, completionHandler: {(data, response, error) -> Void in
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: [])
print(json)
guard let days:[AnyObject] = (json["list"] as! [AnyObject]) else {
throw JSONError.InvalidArray
}
for day in days {
guard let timestamp:Double = day["dt"] as? Double else {
throw JSONError.InvalidKey("dt")
}
print(timestamp)
let date = NSDate(timeIntervalSince1970: NSTimeInterval(timestamp))
guard let weather:[AnyObject] = day["weather"] as? [AnyObject] else {
throw JSONError.InvalidArray
}
guard let desc:String = weather[0]["description"] as? String else {
throw JSONError.InvalidKey("description")
}
guard let icon:String = weather[0]["icon"] as? String else {
throw JSONError.InvalidKey("icon")
}
guard let url = NSURL(string: "http://openweathermap.org/img/w/\(icon).png") else {
throw JSONError.InvalidURL("http://openweathermap.org/img/w/\(icon).png")
}
guard let data = NSData(contentsOfURL: url) else {
throw JSONError.InvalidData
}
guard let image = UIImage(data: data) else {
throw JSONError.InvalidImage
}
guard let temp:AnyObject = day["temp"] else {
throw JSONError.InvalidKey("temp")
}
guard let max:Float = temp["max"] as? Float else {
throw JSONError.InvalidKey("max")
}
let newDay = Item(date: date, description: desc, maxTemp: max, icon: image)
print(newDay)
items.append(newDay)
}
return items // this line fails because I'm in the closure. I want this to be the value returned by the loadData() function.
} catch {
print("Fetch failed: \((error as NSError).localizedDescription)")
}
})
}
答案 0 :(得分:0)
在您的dataHandler
函数中添加一个完成处理程序(在我的示例中名为loadData
):
private func loadData(dataHandler: ([Item])->()) throws {
var items = [Item]()
let jsonUrl = "http://api.openweathermap.org/data/2.5/forecast/daily?units=metric&cnt=7&q=coventry,uk"
print(jsonUrl)
let session = NSURLSession.sharedSession()
guard let shotsUrl = NSURL(string: jsonUrl) else {
throw JSONError.InvalidURL(jsonUrl)
}
session.dataTaskWithURL(shotsUrl, completionHandler: {(data, response, error) -> Void in
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: [])
print(json)
guard let days:[AnyObject] = (json["list"] as! [AnyObject]) else {
throw JSONError.InvalidArray
}
for day in days {
guard let timestamp:Double = day["dt"] as? Double else {
throw JSONError.InvalidKey("dt")
}
print(timestamp)
let date = NSDate(timeIntervalSince1970: NSTimeInterval(timestamp))
guard let weather:[AnyObject] = day["weather"] as? [AnyObject] else {
throw JSONError.InvalidArray
}
guard let desc:String = weather[0]["description"] as? String else {
throw JSONError.InvalidKey("description")
}
guard let icon:String = weather[0]["icon"] as? String else {
throw JSONError.InvalidKey("icon")
}
guard let url = NSURL(string: "http://openweathermap.org/img/w/\(icon).png") else {
throw JSONError.InvalidURL("http://openweathermap.org/img/w/\(icon).png")
}
guard let data = NSData(contentsOfURL: url) else {
throw JSONError.InvalidData
}
guard let image = UIImage(data: data) else {
throw JSONError.InvalidImage
}
guard let temp:AnyObject = day["temp"] else {
throw JSONError.InvalidKey("temp")
}
guard let max:Float = temp["max"] as? Float else {
throw JSONError.InvalidKey("max")
}
let newDay = Item(date: date, description: desc, maxTemp: max, icon: image)
print(newDay)
items.append(newDay)
}
dataHandler(items)
} catch {
print("Fetch failed: \((error as NSError).localizedDescription)")
}
}).resume()
}
do {
try loadData { itemsArray in
print(itemsArray)
}
} catch {
print(error)
}
我已经在Playground中对它进行了测试,它可以正常运行: