The error is: Unexpected non-void return value in void function
I don't know how to solve.
Any help is appreciated!!
This is the code
func NameGet(uid:Double) -> String
{
let url = URL(string: "http://1.15.82.181:8080/api/userinfo?uid="+String(uid))
URLSession.shared.dataTask(with: url!) {(data,response,error) in
do {
if let d = data {
let res = try JSON(data:d)
if let usrname = res[0]["name"].string {
return usrname
}
}else {
print("No Data")
}
} catch {
print ("Error")
}
}.resume()
}
is only returning the in scope of the closure, it's not returning from the NameGet function. The closure that you're passing to URLSession.shared.dataTask (in a trailing position) has (data,response,error) input, but has Void output, so the error is telling you that in a void function (the closure) you're returning a non-void thing (usrname).
You can't return just a String from your NameGet, because you won't get a String by calling URLSession.shared.dataTask...resume(): your NameGet function must be asynchronous, that is, it must return before actually obtaining the relevant data, that could be produced at any point in the future.
To solve this, you could do a couple of things:
if you have access to Combine, you could use URLSession.shared.dataTaskPublisher, that returns Publisher that you then return from the NameGet function;
you could return ((String?) -> Void) -> Void from the function, in order to make the clients handle the asynchronism.
In the second case, your code would change like this:
func NameGet(uid:Double) -> (@escaping (String?) -> Void) -> Void
{
return { gotValue in
let url = URL(string: "http://1.15.82.181:8080/api/userinfo?uid="+String(uid))
URLSession.shared.dataTask(with: url!) {(data,response,error) in
do {
if let d = data {
let res = try JSON(data:d)
if let usrname = res[0]["name"].string {
gotValue(usrname)
}
}else {
print("No Data")
gotValue(nil)
}
} catch {
print ("Error")
gotValue(nil)
}
}.resume()
}
}
Notice that I used String? instead of String: this way you will inform clients that this is done even if no usrname is produced.
If you can, switching to use Swift's native concurrency with async / await will make this much simpler.
let (response, data) = try await URLSession.shared.data(from: url)
// Check response.
let value = try JSONDecoder().decode(MyType.self, from: data)
You should also switch to using Decodable rather than JSON (which I'm assuming is from SwiftyJSON), as it will give you a much better experience overall.
The NameGet function that I wrote is not returning a String anymore, so you can't use it in that context: the Text initializer requires something conforming to StringProtocol, and that closure can't do that.
If used in the context of SwiftUI, @Jon_Shier suggestion is better, and you could use a @StateObject to hold onto a service that fetches your text: take a look at this tutorial.