I have the following problem: I want to make an app which displays information about the sun. I have managed to print the Sunrise in the console, however that’s not the final goal. I want to display it in an NSTextField. This is where it starts to get problematic.
I have tried to add self.sunrise1.stringValue = sunrise
in the private func getData()
. Apparently this doesn’t work and Xcode tells me,
NSControl.stringValue must be used in main thread only
So now I thought I have to return the sunrise
variable. But when I add return(sunrise)
Xcode shows an error:
unexpected non-void return error
So my question is, how do I display the stringValue
of sunrise
in my label sunrise1
?
class ViewController: NSViewController {
@IBOutlet weak var sunrise1: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
let url = "https://api.sunrise-sunset.org/json?lat=36.7201600&lng=-4.4203400"
getData(from: url)
// Do any additional setup after loading the view.
}
private func getData(from url: String) {
let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: {data, response, error in
guard let data = data, error == nil else {
print("something went wrong")
return
}
var result: Response?
do {
result = try JSONDecoder().decode(Response.self, from: data)
}
catch {
print("failed to convert (error.localizedDescription)")
}
guard let json = result else {
return
}
let sunrise = json.results.sunrise
print(sunrise)
})task.resume()
}
}
struct Response: Codable {
let results: MyResult
let status: String
}
struct MyResult: Codable {
let sunrise: String
let sunset: String
let solar_noon: String
let day_length: String
let civil_twilight_begin: String
let civil_twilight_end: String
let nautical_twilight_begin: String
let nautical_twilight_end: String
let astronomical_twilight_begin: String
let astronomical_twilight_end: String
}
2
Answers
Make assignment on main queue, like
Actually, is better to have completion in your
func getData
, so when it finished working you will update your label in completion.As reference I may propose something like:
And now you can call you method in, for example, viewDidLoad() and update your label like that:
To get more information you may learn about
completion block/handlers
, functions with completions and why we must update UI in main thread.If you want your func to return something, you have to declare about that in method signature, for example:
will return 1 which is Int, but if you try to return other type, you will get compilation error.