[What I want to do]
I want to store data from the GetDataFromAPI class getDataFromAPI function in the ViewController class variable data.
つまStumbling points br
I don't know how to return the variables in the closure and it's not working.
We have not been able to implement this part for about a week, and the development has stopped.
Thank you for your cooperation
ViewController.swift
import UIKit
classViewController:UIViewController {
vardata: String=""
override func viewDidLoad(){
super.viewDidLoad()
// Do any additional setup after loading the view, typically from anib.
letgetDataObject=GetDataFromAPI()
let returnData=getDataObject.getDataFromAPI()
data=returnData
print("data:\(data)")
}
}
GetData.swift
import Foundation
structure JsonData:Codable {
// The JSON returned this time is {"key":"value"}
let key —String
}
classGetDataFromAPI {
var formattedData: String=""
funcgetDataFromAPI()->String{
let url : URL = URL (string: "http://127.0.0.1:5000/study")!
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
let task: URLSessionTask = URLSession.shared.dataTask(with:url, completionHandler: {data, response, error in)
letdecoder: JSONDecoder= JSONDecoder()
do{
let data: JsonData=try decoder.decode(JsonData.self, from:data!) // Contains retrieved data
print("Data Retrieved")
self.formattedData=data.key
print(self.formattedData)
} catch{
print("error:", error.localizedDescription)
}
})
task.resume()// Run
return self.formattedData
}
}
URLSessionTask
The trick to master the asynchronous API is to abandon the idea of returning a value (as a return value).The important thing for your app is to make sure you take advantage of the values you get from the server, and the purpose of the development should not be to "force a variable coding that returns asynchronously as a return value".
In today's Swift, which does not have a standard toolset for asynchronous support, it is common to adopt a completion handler pattern in such cases.
class GetDataFromAPI{
func getDataFromAPI(completion:@escaping(String)->Void) {//<- add your own completion handler argument
let url : URL = URL (string: "http://127.0.0.1:5000/study")!
let task: URLSessionTask = URLSession.shared.dataTask(with:url, completionHandler: {data, response, error in)
letdecoder: JSONDecoder= JSONDecoder()
do{
let data: JsonData=try decoder.decode(JsonData.self, from:data!) // Contains retrieved data
print("Data Retrieved")
print(data.key)
Call your own completion handler in completion(data.key)//<-`URLSession.dataTask(with:completionHandler:)` completion handler
} catch{
print("error:", error.localizedDescription)
completion("")//<- Same as above (think about the error)
}
})
task.resume()// Run
// ↑ If you call `task.resume(), don't do anything else.
}
}
(formattedData
is a problem when multiple requests are sent at the same time, so I deleted it.)
This is what the caller looks like.
let getDataObject=GetDataFromAPI()
getDataObject.getDataFromAPI {returnDatain
self.data=returnData//<- Avoid naming variables of type `String` as `data` in actual code
print("data:\(self.data)")
}
Similar questions have been asked many times in the past on this Japanese stack overflow and online blogs and bulletin boards, some of which may include "force asynchronous values back as return values" but all have disadvantages such as "coding complexity only works in certain cases."
Get used to the right way as soon as possible.
© 2024 OneMinuteCode. All rights reserved.