I am new at swift and got problem with getting string from function, I am trying to use completion handler, but something is wrong, could you help me?
After adding [String : String] to func, I cant get rezult, I want to get response and print it. Error: Cannot convert return expresion of type () to return type [String : String]
Requests:
public func login(userName: String, password: String) -> [String : String]{
let loginrequest = JsonRequests.loginRequest(userName: userName, password: password)
return makeWebServiceCall(urlAddress: URL, requestMethod: .post, params: loginrequest, completion: { (JSON : Any) in
print("\(JSON)")
})
}
private func makeWebServiceCall (urlAddress: String, requestMethod: HTTPMethod, params:[String:Any], completion: @escaping (_ JSON : Any) -> ()) {
Alamofire.request(urlAddress, method: requestMethod, parameters: params, encoding: JSONEncoding.default).responseJSON { response in
switch response.result {
case .success:
if let jsonData = response.result.value {
completion(jsonData)
}
case .failure(let error):
if let data = response.data {
let json = String(data: data, encoding: String.Encoding.utf8)
print("Failure Response: \(json)")
}
Calling function:
let retur = Json()
let rezultatas = retur.login(userName: "root", password: "admin01")
print(rezultatas)
Errors:
enter image description here
Welcome to Swift :)
You are mixing synchronous and asynchronous code together.
When you call login
you expect it to return an answer straight away of type [String : String]
.
But in your login
method you then do a network call which can not return straight away...which is why the call to Alamofire.request
takes a completion block as a parameter.
So...you need to change your login
method so it:
- does not return anything straight away (it can not do so...logging in requires us doing a network call remember)
- takes a completion block to invoke once login has succeeded.
This can be done like so:
public func login(userName: String, password: String, loginCompletion: @escaping ([String : String]) -> ())
Here we have a function that takes a userName
of type String
, a password
of type String
and a loginCompletion
of type function
that again takes a [String : String]
dictionary as a parameter. Notice that the method does not return anything.
Now you can call your makeWebServiceCall
almost as before:
let loginrequest = JsonRequests.loginRequest(userName: userName, password: password)
makeWebServiceCall(urlAddress: URL, requestMethod: .post, params: loginrequest, completion: { (JSON : Any) in
//Now we are ready, the login call has returned some data to you.
//You have an attribute named JSON of type Any, which you need to convert to [String : String], and then you can call loginCompletion with that, like so:
loginCompletion(yourConvertedDictionaryHere)
})
Here is the new login
method in its completeness:
public func login(userName: String, password: String, loginCompletion: @escaping ([String : String]) -> ()) {
let loginrequest = JsonRequests.loginRequest(userName: userName, password: password)
makeWebServiceCall(urlAddress: URL, requestMethod: .post, params: loginrequest, completion: { (JSON : Any) in
//Now we are ready, the login call has returned some data to you.
//You have an attribute named JSON of type Any, which you need to convert to [String : String], and then you can call loginCompletion with that, like so:
loginCompletion(yourConvertedDictionaryHere)
})
}
And then you call your login
method like so:
retur.login(userName: "root", password: "admin01") { stringDictionary: [String : String] in
//here you have your stringDictionary which you can use as pleased
}
Hope that helps you.
Make a function definition like this
private func makeWebServiceCall (urlAddress: String, requestMethod: String, params:[String:Any], completion: @escaping (_ JSON : Any) -> ()) {
completion("Make a service call")
}
Make function calling like this
makeWebServiceCall(urlAddress: "", requestMethod: "", params: ["Key" : "value"], completion: { (JSON : Any) in
print("\(JSON)")
})
I have changed DataType of Parameters due to simplicity. Also you can pass any type of data in completion("Make a service call")
.
Hopefully this will help you.