early return from a void-func in Swift?
It is a tricky thing, Swift doesn't require semi-colons (they are optionally used), this makes Swift compiler automatically deduce whether is the next line should be a new line, or a completion for the old one. print()
is a function that returns void. So the word return print("something")
, is valid. So
return
print("Something")
could be deduced as return print("Something")
Your solution is to write
return;
print("Something")
Why Cant I return Void directly in a function
Void is a type, so it cannot be returned. Instead you want to return the representation of Void, which is an empty tuple.
Therefore, try this instead, and this will compile:
func test()->Void{
print("Hello")
}
func test1(){//print Hello
return test()
}
func test2()->Void{// throw error
return ()
}
test1()
For more information about why an empty tupple can be returned in a function that expects to return Void type, search for void in the following link: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html
Swift function with Void return type versus no return type
Simply, there is no difference. -> Void
is just an explicit way of saying that the function returns no value.
From docs:
Functions without a defined return type return a special value of type Void. This is simply an empty tuple, in effect a tuple with zero elements, which can be written as ().
Thus, these three function declarations below are same:
func someFunc() {}
func someFunc() -> Void {}
func someFunc() -> () {}
Why i am getting Unexpected non-void return value in void function error while returning value in swift?
I think AuthManager.shared.saveAddressAsWorkHome(params) { (response) in
this is asynchronous
closure and you are try to return a value in it so you getting this error.
You can not return from asynchronous function directly. You have to add a completion handler on your method and return the value from async in completion handler
So you have to change your function
func getLatDestination(completion : @escaping (Double) -> ()){
var params = [String: Any]()
params[ParametersKeys.access_token] = KeyChain.getAccessToken()!
params[ParametersKeys.address] = googlePlaceObject?.results.first?.formattedAddress
params[ParametersKeys.latitude] = googlePlaceObject?.results.first?.geometry.location.lat
params[ParametersKeys.longitude] = googlePlaceObject?.results.first?.geometry.location.lng
params[ParametersKeys.googlePlaceId] = googlePlaceObject?.results.last?.placeId
params[ParametersKeys.login_type] = 1
AuthManager.shared.saveAddressAsWorkHome(params) { (response) in
if response.flag == RESPONSE_FLAGS.flag_143 {
if let addressData = response.response["addresses"] as? [[String: Any]] {
completion(addressData[0]["lat"])
}
}
}
And when you call your function
getLatDestination(completion: {ret in
print(ret)
})
Return void func from func in Swift
returnVoidFunc
correctly returns a () ->()
function, initFunc
is a reference to that function.
The reason you see ()
printed is because you are evaluating initFunc
, and since it returns ()
, and that's what's printed.
In Swift, by the way, ()
is basically the same as Void
.
Unexpected non-void return value in void function' in swiftui
You are using an asynchronous method (dataTask
). You don't know when it will be finished running (network request). It therefore cannot have a return value. When it finishes it executes the closure (URLSession.shared.dataTask (with: request) {// this block}
).
You would certainly like to do it this way:
class DogManager {
var imageInfos: String?
func getFavoriteDoggo(breed: String) {
guard let url = URL(string: "https://dog.ceo/api/breed/\(breed)/images/random") else {
print("Trouble parsing url")
return
}
URLSession.shared.dataTask(with: url) { data, response, error in
guard error == nil, (response as? HTTPURLResponse)?.statusCode == 200 else {
return
}
if let data = data {
self.imageInfos = String(data: data, encoding: .utf8)
print(self.imageInfos ?? "no infos")
}
}.resume()
}
}
let manager = DogManager()
manager.getFavoriteDoggo(breed: "retriever/golden")
You can test in a Playground.
Now if you want to use SwiftUI
and your View is redrawn when imageInfos
changes you have to change your class to ObservableObject
:
class DogManager: ObservableObject {
@Published var imageInfos: String?
//....//
}
And use it like this:
struct MainView: View {
@StateObject private var dm = DogManager()
var body: some View {
Text(dm.imageInfos ?? "nothing")
.onAppear {
dm.getFavoriteDoggo(breed: "retriever/golden")
}
}
}
iOS15 :
Note that with the introduction of async
/ await
(iOS15) you can write asynchronous methods that have return values (like you did) :
@available(iOS 15.0, *)
func getFavoriteDoggo(breed: String) async -> String? {
guard let url = URL(string: "https://dog.ceo/api/breed/\(breed)/images/random"),
let (data, response) = try? await URLSession.shared.data(from: url),
(response as? HTTPURLResponse)?.statusCode == 200 else { return nil }
return String(data: data, encoding: .utf8)
}
You can use it with the new .task
modifier :
struct MainView: View {
var dm = DogManager()
@State private var imageInfos: String?
var body: some View {
Text(imageInfos ?? "nothing")
.task {
await imageInfos = dm.getFavoriteDoggo(breed: "retriever/golden")
}
}
}
EDIT :
"Hey thank you for helping me out, but this would only work for only 1
dog breed."
First, let's create a new Dog
structure. A Dog
has a breed and the information on its image, which initially does not exist (nil).
struct Dog: Identifiable {
let id = UUID()
let breed: String
var imageInfos: String?
init(_ breed: String) {
self.breed = breed
}
}
Our view will show an array of dogs:
@State private var dogs: [Dog] = ["malamute", "chow", "husky", "samoyed"].map(Dog.init)
Now we change our function that fetches the image of a dog: it takes a Dog
as a parameter, and returns (when it has finished) a Dog
(with imageInfos
filled) :
func updateImageOf(dog: Dog) async -> Dog {
var newDog = dog
guard let url = URL(string: "https://dog.ceo/api/breed/\(dog.breed)/images/random"),
let (data, response) = try? await URLSession.shared.data(from: url),
(response as? HTTPURLResponse)?.statusCode == 200 else { return dog }
newDog.imageInfos = String(data: data, encoding: .utf8)
return newDog
}
We create a second function that does the same for several dogs.
func updateImagesOf(favoriteDogs: [Dog]) async -> [Dog] {
var results: [Dog] = []
await withTaskGroup(of: Dog.self) { group in
for dog in favoriteDogs {
group.async {
await self.updateImageOf(dog: dog)
}
}
for await result in group {
results.append(result)
}
}
return results
}
We use this function in our View
:
struct MainView: View {
var dm = DogManager()
@State private var dogs: [Dog] = ["malamute", "chow", "husky", "samoyed"].map(Dog.init)
var body: some View {
List(dogs) { dog in
HStack {
Text(dog.breed)
.padding(.trailing, 40)
Text(dog.imageInfos ?? "rien")
}
}
.task {
await dogs = dm.updateImagesOf(favoriteDogs: dogs)
}
}
}
It works (Simulator, Xcode 13 beta2)
Swift - unexpected non-void return value in void function
You are missing return type in your method header.
func calculateDistance(location: CLLocation) -> CLLocationDistance {
Seemingly my answer looks as an inferior duplicate, so some addition.
Functions (including methods, in this case) declared without return types are called as void function, because:
func f() {
//...
}
is equivalent to:
func f() -> Void {
//...
}
Usually, you cannot return any value from such void functions.
But, in Swift, you can return only one value (I'm not sure it can be called as "value"), "void value" represented by ()
.
func f() {
//...
return () //<- No error here.
}
Now, you can understand the meaning of the error message:
unexpected non-void return value in void function
You need to change the return value or else change the return type Void
to some other type.
Related Topics
Remove Multiple Indices from Array
Strange Error Nw_Protocol_Get_Quic_Image_Block_Invoke Dlopen Libquic Failed
How to Animate Transition Between Views in Swiftui
Storyboard Tableview with Segues to Multiple Views
Swift 3:Fatal Error: Double Value Cannot Be Converted to Int Because It Is Either Infinite or Nan
What Is Other Option Available in Swift Instead of Refactoring and Renaming Class or Attribute Name
What Is the Usecase for Ignored Parameters in Swift
How to Set an Attributed Title Color for State in Swift
Difference Between Println and Print in Swift
How to Resume Audio After Interruption in Swift
Filter by Multiple Array Conditions
How to Convert a Swift String to Cfstring
How to Detect a 'Click' Gesture in Swiftui Tvos
What Is the Role of Avcapturedevicetype.Builtindualcamera
Swift Difference Between Final Var and Non-Final Var | Final Let and Non-Final Let