因此,我在运行API调用时遇到问题,其响应包括另一个API调用。
这是第一个功能:
class APICaller{
weak var delegate:APIDelegate?
func getCharacter(x:Int){
let character = CharacterModel()
let url = URL(string: "https://swapi.co/api/people/\(x)/")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil{
print("Error downloading character information. Empty character returned.")
} else {
if let content = data {
do{
let charJSON = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any]
character.name = (charJSON?["name"] as? String)?.description ?? ""
character.height = Int((charJSON?["height"] as? String)?.description ?? "0") ?? 0
character.mass = Int((charJSON?["mass"] as? String)?.description ?? "0") ?? 0
character.hairColor = (charJSON?["hair_color"] as? String)?.description ?? ""
character.skinColor = (charJSON?["skin_color"] as? String)?.description ?? ""
character.eyeColor = (charJSON?["eye_color"] as? String)?.description ?? ""
character.birthYear = (charJSON?["birth_year"] as? String)?.description ?? ""
character.gender = (charJSON?["gender"] as? String)?.description ?? ""
character.homeWorld = self.getPlanet(uri: (charJSON?["homeworld"] as? String)?.description ?? "")
//The homeward part of the response is another URL and as such requires another API Call to get anything meaningful
DispatchQueue.main.async {
self.delegate?.didGetStarWarsCharacter(characterData:character)
}
}catch{
print("Error downloading character information. Empty or incomplete character returned")
}
}
}
}
task.resume()
}
private func getPlanet(uri:String)->String{
if uri == ""{
return uri // return empty string if the original call doesn't get anything.
}
var result = ""
let url = URL(string:uri)
let task = URLSession.shared.dataTask(with: url!){(data,response,error)->Void in
if error != nil{
result = "No Planet Found"
}else{
if let planet = data{
do{
let planetJSON = try JSONSerialization.jsonObject(with: planet, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String:Any]
//print(planetJSON?["name"] as? String ?? "No Planet")
result = (planetJSON?["name"] as? String)?.description ?? "No Planet Found"
}catch{
result = "No Planet Found"
}
}
}
}// end of task, result is lost due to multithreading
task.resume()
return result
}
}
所以我理解为getPlanet
运行任务发生在另一个线程上,并且此方法在任务完成运行之前返回。因此,当委托获取CharacterModel时,其homeWorld参数为空。
例如,如果我在print(character.homeWorld)
函数运行后调用getPlanet
,我会收到一个空字符串。
我能解决的是解决这个问题的好方法。
答案 0 :(得分:1)
getPlanet正在执行异步调用。 result
实例不会保留接收的数据。而不是使用getPlanet中的完成块并在接收数据时调用此完成块。像这样的东西。请阅读closures。
class APICaller{
weak var delegate:APIDelegate?
func getCharacter(x:Int){
let character = CharacterModel()
let url = URL(string: "https://swapi.co/api/people/\(x)/")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil{
print("Error downloading character information. Empty character returned.")
} else {
if let content = data {
do{
let charJSON = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any]
character.name = (charJSON?["name"] as? String)?.description ?? ""
character.height = Int((charJSON?["height"] as? String)?.description ?? "0") ?? 0
character.mass = Int((charJSON?["mass"] as? String)?.description ?? "0") ?? 0
character.hairColor = (charJSON?["hair_color"] as? String)?.description ?? ""
character.skinColor = (charJSON?["skin_color"] as? String)?.description ?? ""
character.eyeColor = (charJSON?["eye_color"] as? String)?.description ?? ""
character.birthYear = (charJSON?["birth_year"] as? String)?.description ?? ""
character.gender = (charJSON?["gender"] as? String)?.description ?? ""
self.getPlanet(uri: (charJSON?["homeworld"] as? String)?.description ?? "", completion:
{ (result:String) in
character.homeWorld = result
DispatchQueue.main.async {
self.delegate?.didGetStarWarsCharacter(characterData:character)
}
}
)
//The homeward part of the response is another URL and as such requires another API Call to get anything meaningful
}catch{
print("Error downloading character information. Empty or incomplete character returned")
}
}
}
}
task.resume()
}
private func getPlanet(uri:String, completion:@escaping (_ response:String)->Void){
if uri == ""{
completion(uri) // return empty string if the original call doesn't get anything.
}
var result = ""
let url = URL(string:uri)
let task = URLSession.shared.dataTask(with: url!){(data,response,error)->Void in
if error != nil{
result = "No Planet Found"
}else{
if let planet = data{
do{
let planetJSON = try JSONSerialization.jsonObject(with: planet, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String:Any]
//print(planetJSON?["name"] as? String ?? "No Planet")
result = (planetJSON?["name"] as? String)?.description ?? "No Planet Found"
}catch{
result = "No Planet Found"
}
completion(result)
}
}
}// end of task, result is lost due to multithreading
task.resume()
}
}