Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected non-void return value in void function Swift3

Tags:

ios

swift

I have a function that returns either a class object or nil. The function's purpose is to check if a Chat exists. The chat ID's are stored in MySQL. If the ID exists, I perform a Firebase reference to get a snapshot and then get the object. If the ID does not exist, I return nil:

func findChat(string: String) -> Chat? {

    var returnValue: (Chat?)
    let url = getChatsURL
    let Parameters = [ "title" : string ]

    Alamofire.request("\(url)", method: .post, parameters: Parameters).validate().responseString { response in
            if let anyResponse = response.result.value {
                self.responseFromServer = anyResponse
            }

            if self.responseFromServer == "" {
              returnValue = nil
            } else {
                let ref = DatabaseReference.chats.reference()
                let query = ref.queryOrdered(byChild: "uid").queryEqual(toValue: (self.responseFromServer))
                query.observe(.childAdded, with: { snapshot in
                returnValue = Chat(dictionary: snapshot.value as! [String : Any])
            })
        }
        return returnValue
    }

}

However, at return returnValue I am getting

Unexpected non-void return value in void function.

Any thoughts of what I could be missing?

like image 421
Sente Avatar asked Aug 28 '17 18:08

Sente


People also ask

Does non-void function need return?

The analyzer has detected a non-void function with an execution path that does not return a value. Such a function results in undefined behavior. Flowing off the end of a non-void function with no 'return' results in undefined behavior.

Why does void not return a value?

void is a type to represent nothing. That is a subtle difference : the representation is still required, even though it represents nothing. This type is used as function's return type which returns nothing. This is also used to represent generic data, when it is used as void* .


2 Answers

The problem is that you are trying to return a non-void value from inside a closure, which only returns from the closure, but since that closure expects a void return value, you receive the error.

You cannot return from an asynchronous function using the standard return ... syntax, you have to declare your function to accept a completion handler and return the value from the async network call inside the completion handler.

func findChat(string: String, completion: @escaping (Chat?)->()) {
    var returnValue: (Chat?)
    let url = getChatsURL
    let Parameters = [ "title" : string ]

    Alamofire.request("\(url)", method: .post, parameters: Parameters).validate().responseString { response in
        if let anyResponse = response.result.value {
            self.responseFromServer = anyResponse
        }
        if self.responseFromServer == "" {
            completion(nil)
        } else {
            let ref = DatabaseReference.chats.reference()
            let query = ref.queryOrdered(byChild: "uid").queryEqual(toValue: (self.responseFromServer))
                query.observe(.childAdded, with: { snapshot in
                completion(Chat(dictionary: snapshot.value as! [String : Any]))
            })
        }
    }
}

Then you can call this function and use the return value like this:

findChat(string: "inputString", completion: { chat in
    if let chat = chat {
        //use the return value
    } else {
        //handle nil response
    }
})
like image 77
Dávid Pásztor Avatar answered Sep 27 '22 23:09

Dávid Pásztor


Your block is executed asynchronously, but you're trying to return a value from the enclosing function. It doesn't work that way. Your findChat function needs to take a completion block itself instead of returning a value, and then you can call that completion block from the point where you're trying to say return returnValue.

like image 23
Lily Ballard Avatar answered Sep 27 '22 22:09

Lily Ballard