swiftyjson objective example ios swift alamofire

ios - objective - swiftyjson alamofire



Cómo devolver valor de Alamofire (5)

Detalles

xCode 9.1, Swift 4

caracteristicas:

  • Código fácil de leer
  • Plantillas listas (es fácil agregar más solicitudes)
  • Solución integrada con procesamiento de datos asíncrono.
  • Ejemplos completos

Muestra 1

Devolver datos usando cierre

Data1.searchRequest(term: "jack johnson") { json, error in print(error ?? "nil") print(json ?? "nil") print("Update views") }

Muestra completa 1

Clase de datos

import Alamofire class Data1 { static fileprivate let queue = DispatchQueue(label: "requests.queue", qos: .utility) static fileprivate let mainQueue = DispatchQueue.main fileprivate class func make(request: DataRequest, closure: @escaping (_ json: [String: Any]?, _ error: Error?)->()) { request.responseJSON(queue: Data1.queue) { response in // print(response.request ?? "nil") // original URL request // print(response.response ?? "nil") // HTTP URL response // print(response.data ?? "nil") // server data //print(response.result ?? "nil") // result of response serialization switch response.result { case .failure(let error): Data1.mainQueue.async { closure(nil, error) } case .success(let data): Data1.mainQueue.async { closure((data as? [String: Any]) ?? [:], nil) } } } } class func searchRequest(term: String, closure: @escaping (_ json: [String: Any]?, _ error: Error?)->()) { let request = Alamofire.request("https://itunes.apple.com/search?term=/(term.replacingOccurrences(of: " ", with: "+"))") Data1.make(request: request) { json, error in closure(json, error) } } }

UIViewController

class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. Data1.searchRequest(term: "jack johnson") { json, error in print(error ?? "nil") print(json ?? "nil") print("Update views") } } }

Muestra 2

Devolver datos usando delegado

// .... var data = Data2() data.delegate = self data.searchRequest(term: "jack johnson") // .... extension ViewController: Data2Delegate { func searchRequest(response json: [String : Any]?, error: Error?) { print(error ?? "nil") print(json ?? "nil") print("Update views") } }

Muestra completa 2

Clase de datos

import Alamofire protocol Data2Delegate: class { func searchRequest(response json: [String: Any]?, error: Error?) } class Data2 { fileprivate let queue = DispatchQueue(label: "requests.queue", qos: .utility) fileprivate let mainQueue = DispatchQueue.main weak var delegate: Data2Delegate? fileprivate func make(request: DataRequest, closure: @escaping (_ json: [String: Any]?, _ error: Error?)->()) { request.responseJSON(queue: queue) { response in // print(response.request ?? "nil") // original URL request // print(response.response ?? "nil") // HTTP URL response // print(response.data ?? "nil") // server data //print(response.result ?? "nil") // result of response serialization switch response.result { case .failure(let error): self.mainQueue.async { closure(nil, error) } case .success(let data): self.mainQueue.async { closure((data as? [String: Any]) ?? [:], nil) } } } } func searchRequest(term: String) { let request = Alamofire.request("https://itunes.apple.com/search?term=/(term.replacingOccurrences(of: " ", with: "+"))") make(request: request) { json, error in self.delegate?.searchRequest(response: json, error: error) } } }

UIViewController

import UIKit class ViewController: UIViewController { private var data = Data2() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. data.delegate = self data.searchRequest(term: "jack johnson") } } extension ViewController: Data2Delegate { func searchRequest(response json: [String : Any]?, error: Error?) { print(error ?? "nil") print(json ?? "nil") print("Update views") } }

Muestra 3

Devolver datos usando PromiseKit

_ = data.searchRequest(term: "jack johnson").then { response in print(response.error ?? "nil") print(response.json ?? "nil") print("Update views") return .void }

Muestra completa 3

Importación de clase de datos Importación de Alamofire PromiseKit

class Data3 { fileprivate let queue = DispatchQueue(label: "requests.queue", qos: .utility) fileprivate let mainQueue = DispatchQueue.main fileprivate func make(request: DataRequest) -> Promise<(json:[String: Any]?, error: Error?)> { return Promise { fulfill, reject in request.responseJSON(queue: queue) { response in // print(response.request ?? "nil") // original URL request // print(response.response ?? "nil") // HTTP URL response // print(response.data ?? "nil") // server data //print(response.result ?? "nil") // result of response serialization switch response.result { case .failure(let error): self.mainQueue.async { fulfill((nil, error)) } case .success(let data): self.mainQueue.async { fulfill(((data as? [String: Any]) ?? [:], nil)) } } } } } func searchRequest(term: String) -> Promise<(json:[String: Any]?, error: Error?)> { let request = Alamofire.request("https://itunes.apple.com/search?term=/(term.replacingOccurrences(of: " ", with: "+"))") return make(request: request) } } extension AnyPromise { class var void: AnyPromise { return AnyPromise(Promise<Void>()) } }

UIViewController

import UIKit import PromiseKit class ViewController: UIViewController { private var data = Data3() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. _ = data.searchRequest(term: "jack johnson").then { response in print(response.error ?? "nil") print(response.json ?? "nil") print("Update views") return .void } } }

Estoy haciendo llamadas de URL a través de una API que creé usando swift de la siguiente manera:

class API { let apiEndPoint = "endpoint" let apiUrl:String! let consumerKey:String! let consumerSecret:String! var returnData = [:] init(){ self.apiUrl = "https://myurl.com/" self.consumerKey = "my consumer key" self.consumerSecret = "my consumer secret" } func getOrders() -> NSDictionary{ return makeCall("orders") } func makeCall(section:String) -> NSDictionary{ let params = ["consumer_key":"key", "consumer_secret":"secret"] Alamofire.request(.GET, "/(self.apiUrl)//(self.apiEndPoint + section)", parameters: params) .authenticate(user: self.consumerKey, password: self.consumerSecret) .responseJSON { (request, response, data, error) -> Void in println("error /(request)") self.returnData = data! as NSDictionary } return self.returnData } }

Llamo a esta API en mi UITableViewController para llenar la tabla con la biblioteca SwiftyJSON. Sin embargo, mi returnData de la API siempre está vacío. No hay ningún problema con las llamadas de Alomofire, ya que puedo recuperar el valor con éxito. Mi problema es cómo se supone que debo llevar estos data a mi controlador de vista de tabla.

var api = API() api.getOrders() println(api.returnData) // returnData is empty


Como señala Mattt, Alamofire está devolviendo datos de forma asincrónica a través de un patrón de "controlador de finalización", por lo que debe hacer lo mismo. No puede return el valor de inmediato, sino que desea cambiar su método para no devolver nada, sino utilizar un patrón de cierre del controlador de finalización.

Hoy en día, eso podría verse así:

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") } } }

Luego, cuando desee llamarlo, use este parámetro de cierre de completion (en cierre final, si lo desea):

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 //


Del Alamofire README (énfasis agregado):

La creación de redes en Alamofire se realiza de forma asincrónica. La programación asincrónica puede ser una fuente de frustración para los programadores que no están familiarizados con el concepto, pero hay muy buenas razones para hacerlo de esta manera.

En lugar de bloquear la ejecución para esperar una respuesta del servidor, se especifica una devolución de llamada para manejar la respuesta una vez que se recibe. El resultado de una solicitud solo está disponible dentro del alcance de un controlador de respuesta. Cualquier ejecución supeditada a la respuesta o los datos recibidos del servidor debe realizarse dentro de un controlador .


El siguiente es el flujo completo para realizar la ''Acción de inicio de sesión'' usando Alamofire y Swift.

Alamofire v3.3 Swift 2.2 Xcode 7.3

He usado GCD y MBProgressHUD para mi propia conveniencia. Refactoriza y usa como quieras :)

func loginBtnTapped(sender: AnyObject) { MBProgressHUD.showHUDAddedTo(self.view, animated: true) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { let loginInfo : Dictionary<String,AnyObject> = ["email":"[email protected]","password":"abc123"] self.loginUser(loginInfo) { responseObject, error in print("/(responseObject) /n /(error) ") // Parsing JSON Below let status = Int(responseObject?.objectForKey("status") as! String) if status == 1 { // Login Successfull...Move To New VC } else { print(responseObject?.objectForKey("message"))! as! String) } return } dispatch_async(dispatch_get_main_queue()) { MBProgressHUD.hideHUDForView(self.view, animated: true) } } } func loginUser(parameters:NSDictionary, completionHandler: (NSDictionary?, NSError?) -> ()) { self.postRequest("http://qa.company.com/project/index.php/user/login", paramDict: parameters as? Dictionary<String, AnyObject>, completionHandler: completionHandler) } func postRequest(urlString: String, paramDict:Dictionary<String, AnyObject>? = nil, completionHandler: (NSDictionary?, NSError?) -> ()) { Alamofire.request(.POST, urlString, parameters: paramDict) .responseJSON { response in switch response.result { case .Success(let JSON): completionHandler(JSON as? NSDictionary, nil) case .Failure(let error): completionHandler(nil, error) } } }


Para analizar un json usando Swifty JSON, así es como lo estoy haciendo.

Para @Jenita _Alice4Real

func uploadScans(parameters: [String: AnyObject], completionHandler: (AnyObject?, NSError?) -> ()) { makePostCall(CommonFunctions().getSaveSKUDataUrl(), parameters: parameters,completionHandler: completionHandler) } func makePostCall(url: String, parameters: [String: AnyObject], completionHandler: (AnyObject?, NSError?) -> ()) { Alamofire.request(.POST, url, parameters: parameters) .responseJSON { response in switch response.result { case .Success(let value): completionHandler(value, nil) case .Failure(let error): completionHandler(nil, error) } } } uploadScans(params) { responseObject, error in let json = JSON(responseObject!) }