Returning a Value from a Function with Alamofire and Swiftyjson

Returning a value from a function with Alamofire and SwiftyJson

An example of a completion handler for your getMenu function, assuming menu is the value you want to "return":

class MenuManager {

// the handler takes an EKMenu argument
class func getMenu(menu_id: Int, completionHandler: (menu: EKMenu) -> ()) {

let url="https://www.domain.com/arc/v1/api/menus/\(menu_id)/mobile"
Alamofire.request(.GET, url).responseJSON() {
(_, _, data, _) in
println("within menu request")
var json=JSON(data!)
var menu=EKMenu()
menu.name=json["menu"]["name"].stringValue
for (key, subJson) in json["menu"]["menu_headers"]{
EKMenu.processMenuHeaders(subJson)
}

// wrap the resulting EKMenu in the handler
completionHandler(menu)

}
}

class func processMenuHeaders(menu_header: JSON){
let mh_name=menu_header["name"].stringValue
println("mh_name: \(mh_name)")
for (key, subJson) in menu_header["menu_headers"]{
EKMenu.processMenuHeaders(subJson)
}
}

}

MenuManager.getMenu(42, completionHandler: { menu in
// here the handler gives you back the value
println(menu)
})

Alamofire and SwiftyJSon get value outside request function

You can't subscript with Any and after you converting JSON to [String:Any] if you are trying .stringValue with subscripting Dictionary then Dictionary doesn't have any property stringValue you are mixing two things here SwiftyJSON and Swift native type. I will access your JSON response this way.

First get clear about how you get value of ubus_rpc_session from your JSON response. You can't directly get value of ubus_rpc_session from your JSON response because it is inside the 2nd object in your result array,so to get the ubus_rpc_session try like this way.

retur.login(userName: userName.text!, password: password.text!) { (json) in
print(json)
if let dic = json as? [String:Any], let result = dic["result"] as? [Any],
let subDic = result.last as? [String:Any],
let session = subDic["ubus_rpc_session"] as? String {

print(session)
}
}

If you want to work with SwiftyJSON then you can get value of ubus_rpc_session this way.

retur.login(userName: userName.text!, password: password.text!) { (json) in
print(json)

let jsonDic = JSON(json)
print(jsonDic["result"][1]["ubus_rpc_session"].stringValue)
}

How to return value from Alamofire

As mattt points out, Alamofire is returning data asynchronously via a “completion handler” pattern, so you must do the same. You cannot just return the value immediately, but you instead want to change your method to not return anything, but instead use a completion handler closure pattern.

Nowadays, that might look like:

func getOrders(completionHandler: @escaping (Result<[String: Any]>) -> Void) {
performRequest("orders", completion: completionHandler)
}

func performRequest(_ section: String, completion: @escaping (Result<[String: Any]>) -> Void) {
let url = baseURL.appendingPathComponent(section)
let params = ["consumer_key": "key", "consumer_secret": "secret"]

Alamofire.request(url, parameters: params)
.authenticate(user: consumerKey, password: consumerSecret)
.responseJSON { response in
switch response.result {
case .success(let value as [String: Any]):
completion(.success(value))

case .failure(let error):
completion(.failure(error))

default:
fatalError("received non-dictionary JSON response")
}
}
}

Then, when you want to call it, you use this completion closure parameter (in trailing closure, if you want):

api.getOrders { result in
switch result {
case .failure(let error):
print(error)

case .success(let value):
// use `value` here
}
}

// but don't try to use the `error` or `value`, as the above closure
// has not yet been called
//

Return a value in a nested JSON array, using Alamofire and Swift

You can use Decodable to get the desired result.

struct RootResponse: Decodable {

let destinationAddresses, originAddresses: [String]
let rows: [Rows]
let status: String
}

struct Rows: Decodable {

let elements: [Elements]
}

struct Elements: Decodable {

let distance, duration: Details
let status: String
}

struct Details: Decodable {
let text, value: String
}

This will be your model file and once you have added it then you can go back to your function and use it as:

func distanceMatrix(startLocation: String, endLocation: String) {
let myOrigin = startLocationTFText
let myDestination = destinationLocationTFText

let url = "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=\(myOrigin)&destinations=\(myDestination)&key=API_Key"

let encodedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)

AF.request(encodedUrl!).responseJSON { response in
print(response.request as Any)
print(response.response as Any)
print(response.data as Any)
print(response.result as Any)

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

guard let json = try? decoder.decode(RootResponse.self, from: response.data) else { print("Unable to parse JSON"); return }

print(json)
print(json.rows.first?.elements.first?.distance.value) // This is how you can get the value, but it will be better to safely unwrap them and I have also used first? to get the first object but this is an array and you can always use a for loop for further purpose
}

Alamofire request with SwiftyJSON parameters

I found the solution by myself:

let params = ["customObjects": customObjects.map({$0.toDictionary()})]

And here the toDictionary() func inside my CustomObject:

func toDictionary() -> [String: Any] {
let dict: [String: Any] = [
"exampleKey": "exampleValue",
"exampleKey2": "exampleValue2"
]

return dict
}

I guess this is because you can setup Alamofire with encoding: JSONEncoding.default.

Return value from Alamofire request in Swift 2.2

Take a look at the most frequently asked questions on the site. Your problem is one of timing – if you were to print both of the results inside the completion handler, and outside, you will see that the function returns well before the completion handler executes. They are asynchronous, and the function call itself is gone before the results come back



Related Topics



Leave a reply



Submit