Здесь существует более глубокая проблема, когда вы пытаетесь вернуть данные из метода, который выполняется асинхронно. Вы должны изменить свой метод ничего не возвращает, само по себе, а поставить обработчик завершения, с помощью которого вы можете асинхронно передавать обратно соответствующие данные:
class func downloadJSONFile(completionHandler:(AnyObject?) ->()) {
let requestURL: NSURL = NSURL(string: "http://www.learnswiftonline.com/Samples/subway.json")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) { data, response, error in
// check for fundamental networking errors
guard error == nil && data != nil else {
print(error)
completionHandler(nil)
return
}
// check to see if status code found, and if so, that it's 200
guard let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200 else {
completionHandler(nil)
return
}
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:[])
completionHandler(json)
} catch let parseError as NSError {
print("Error with Json: \(parseError)")
completionHandler(nil)
}
}
task.resume()
}
, а затем вы называете его, используя обработчик завершения (или использование отставая синтаксис закрытия, как показано ниже):
APIClass.downloadJSONFile() { json in
guard json != nil else {
print("there was some problem")
return
}
// now you can use `json` here
dispatch_async(dispatch_get_main_queue()) {
// and if you're doing any model or UI updates, dispatch that back to the main queue
}
}
// but do not use `json` here, as the above runs asynchronously
Обратите внимание, если вы хотите, чтобы предоставить информацию об ошибках обратно в вызывающую, вы можете изменить его и возвращать информацию об ошибке, например:
enum DownloadError : ErrorType {
case NetworkError(NSError?)
case NotHTTPResponse
case InvalidHTTPResponse(Int)
case JSONError(NSError)
}
class func downloadJSONFile(completionHandler:(AnyObject?, ErrorType?) ->()) {
let requestURL: NSURL = NSURL(string: "http://www.learnswiftonline.com/Samples/subway.json")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) { data, response, error in
guard error == nil && data != nil else {
completionHandler(nil, DownloadError.NetworkError(error))
return
}
guard let httpResponse = response as? NSHTTPURLResponse else {
completionHandler(nil, DownloadError.NotHTTPResponse)
return
}
guard httpResponse.statusCode == 200 else {
completionHandler(nil, DownloadError.InvalidHTTPResponse(httpResponse.statusCode))
return
}
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:[])
completionHandler(json, nil)
} catch let parseError as NSError {
completionHandler(nil, DownloadError.JSONError(parseError))
}
}
task.resume()
}
И, очевидно, вызов изменится принимать оба параметра:
APIClass.downloadJSONFile() { json, error in
guard json != nil && error == nil else {
print("there was some problem \(error)")
return
}
// and then it would be like before ...
}
Вы не * возвращение * от асинхронного вызова. Пример здесь: http://stackoverflow.com/a/35358750/2227743 Кроме того, вы не должны * принудить приведение * ответа, его может и не быть, поэтому сначала проверьте параметр ошибки. – Moritz