2014-09-21 1 views
1

désolé pour mon mauvais anglais :)Poignée Réponse JSON avec Alamofire à Swift

J'ai un problème pour analyser la réponse JSON sur Alamofire à Swift pour une application iOS. J'ai écrit une fonction pour retourner une chaîne de réponse JSON. La gestion des requêtes et des réponses que je fais avec Alamofire et le traitement JSON que je fais avec SwiftyJSON. Au début, je déclare un var appelé jsonString avec la valeur test. Ensuite, je fais une demande à un service REST et obtenir une réponse JSON en cliquant sur un bouton. Cette réponse je veux revenir avec la fonction ping (url: String). À la fin, j'imprime la réponse retournée comme un test. Mais au premier clic sur le bouton la valeur de retour de ping est test et pas la chaîne JSON de la réponse. Au second clic sur le bouton, j'obtiens la bonne valeur de retour. Pourquoi j'ai ce problème. La requête Alamofire est-elle une opération asynchrone? Je veux attendre la réponse. Comment puis-je résoudre le problème pour obtenir la bonne valeur au premier clic et non tester comme valeur?

Voici mon code:

var jsonString:String = "test" 

func ping(url:String) -> String { 

    Alamofire.request(.GET, url) 
     .response { 
      (request, response, data, error) -> Void in 

      let json = JSONValue(data as? NSData) 
      self.jsonString = json.rawJSONString 
    } 

    return self.jsonString 
} 

@IBAction func checkOnlineStatus(sender: UIButton) { 

    let response:String = ping("http://test.com") 

    println(response)} 

Répondre

3

Dans le premier clic, le code

return self.jsonString 

se déroulera avant

.response { 
     (request, response, data, error) -> Void in 

     let json = JSONValue(data as? NSData) 
     self.jsonString = json.rawJSONString 
} 

vous obtiendrez nil former le self.jsonString dans la première fois, votre deuxième clic obtiendra les données de demande du premier clic.

Si vous utilisez SwiftyJSON et Alamofire vous pouvez essayer Alamofire-SwiftyJSON

+0

merci beaucoup ... je vais essayer :) – Martin

1

Vous pouvez également essayer de courir

dispatch_sync(dispatch_get_main_queue()) { 
    // insert code you need done the first time around - it will wait 
} 
0

La problème que vous HAVING est que vous essayez de return le résultat d'une méthode asynchrone synchrone.

Vous avez deux solutions:

  1. Retour le résultat de manière asynchrone
  2. Attendez que l'appel asynchrone pour terminer

J'ai écrit une réponse à cette même question il y a quelques minutes sur ce fil, je vais vous suggérer de le vérifier: https://stackoverflow.com/a/33130512/422288

0
pod 'Alamofire' 
pod 'SwiftyJSON' 
pod 'ReachabilitySwift' 

import UIKit import Alamofire import SwiftyJSON import SystemConfiguration 

class WebServiceHelper: NSObject { 

typealias SuccessHandler = (JSON) -> Void 
typealias FailureHandler = (Error) -> Void 

// MARK: - Internet Connectivity 

class func isConnectedToNetwork() -> Bool { 

    var zeroAddress = sockaddr_in() 
    zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size) 
    zeroAddress.sin_family = sa_family_t(AF_INET) 

    guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, { 
     $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { 
      SCNetworkReachabilityCreateWithAddress(nil, $0) 
     } 
    }) else { 
     return false 
    } 

    var flags: SCNetworkReachabilityFlags = [] 
    if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) { 
     return false 
    } 

    let isReachable = flags.contains(.reachable) 
    let needsConnection = flags.contains(.connectionRequired) 

    return (isReachable && !needsConnection) 
} 

// MARK: - Helper Methods 

class func getWebServiceCall(_ strURL : String, isShowLoader : Bool, success : @escaping SuccessHandler, failure : @escaping FailureHandler) 
{ 
    if isConnectedToNetwork() { 

     print(strURL) 

     if isShowLoader == true { 

      AppDelegate.getDelegate().showLoader() 
     } 

     Alamofire.request(strURL).responseJSON { (resObj) -> Void in 

      print(resObj) 

      if resObj.result.isSuccess { 
       let resJson = JSON(resObj.result.value!) 

       if isShowLoader == true { 
        AppDelegate.getDelegate().dismissLoader() 
       } 

       debugPrint(resJson) 
       success(resJson) 
      } 
      if resObj.result.isFailure { 
       let error : Error = resObj.result.error! 

       if isShowLoader == true { 
        AppDelegate.getDelegate().dismissLoader() 
       } 
       debugPrint(error) 
       failure(error) 
      } 
     } 
    }else { 


     CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!) 
    } 
} 

class func getWebServiceCall(_ strURL : String, params : [String : AnyObject]?, isShowLoader : Bool, success : @escaping SuccessHandler, failure :@escaping FailureHandler){ 
    if isConnectedToNetwork() { 

     if isShowLoader == true { 
      AppDelegate.getDelegate().showLoader() 
     } 


     Alamofire.request(strURL, method: .get, parameters: params, encoding: JSONEncoding.default, headers: nil).responseJSON(completionHandler: {(resObj) -> Void in 

      print(resObj) 

      if resObj.result.isSuccess { 
       let resJson = JSON(resObj.result.value!) 

       if isShowLoader == true { 
        AppDelegate.getDelegate().dismissLoader() 
       } 

       success(resJson) 
      } 
      if resObj.result.isFailure { 
       let error : Error = resObj.result.error! 

       if isShowLoader == true { 
        AppDelegate.getDelegate().dismissLoader() 
       } 

       failure(error) 
      } 

     }) 
    } 
else { 

     CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!) 
} 

} 



class func postWebServiceCall(_ strURL : String, params : [String : AnyObject]?, isShowLoader : Bool, success : @escaping SuccessHandler, failure :@escaping FailureHandler) 
{ 
    if isConnectedToNetwork() 
    { 

     if isShowLoader == true 
     { 
      AppDelegate.getDelegate().showLoader() 
     } 

     Alamofire.request(strURL, method: .post, parameters: params, encoding: JSONEncoding.default, headers: nil).responseJSON(completionHandler: {(resObj) -> Void in 

      print(resObj) 

      if resObj.result.isSuccess 
      { 
       let resJson = JSON(resObj.result.value!) 

       if isShowLoader == true 
       { 
        AppDelegate.getDelegate().dismissLoader() 
       } 

       success(resJson) 
      } 

      if resObj.result.isFailure 
      { 
       let error : Error = resObj.result.error! 

       if isShowLoader == true 
       { 
        AppDelegate.getDelegate().dismissLoader() 
       } 

       failure(error) 
      } 
     }) 
    }else { 
     CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!) 
    } 
} 


class func postWebServiceCallWithImage(_ strURL : String, image : UIImage!, strImageParam : String, params : [String : AnyObject]?, isShowLoader : Bool, success : @escaping SuccessHandler, failure : @escaping FailureHandler) 
{ 
    if isConnectedToNetwork() { 
     if isShowLoader == true 
     { 
      AppDelegate.getDelegate().showLoader() 
     } 

     Alamofire.upload(
      multipartFormData: { multipartFormData in 
       if let imageData = UIImageJPEGRepresentation(image, 0.5) { 
        multipartFormData.append(imageData, withName: "Image.jpg") 
       } 

       for (key, value) in params! { 

        let data = value as! String 

        multipartFormData.append(data.data(using: String.Encoding.utf8)!, withName: key) 
        print(multipartFormData) 
       } 
      }, 
      to: strURL, 
      encodingCompletion: { encodingResult in 
       switch encodingResult { 
       case .success(let upload, _, _): 
        upload.responseJSON { response in 
         debugPrint(response) 
         //let datastring = String(data: response, encoding: String.Encoding.utf8) 
         // print(datastring) 
        } 
       case .failure(let encodingError): 
        print(encodingError) 
        if isShowLoader == true 
        { 
         AppDelegate.getDelegate().dismissLoader() 
        } 

        let error : NSError = encodingError as NSError 
        failure(error) 
       } 

       switch encodingResult { 
       case .success(let upload, _, _): 
        upload.responseJSON { (response) -> Void in 

         if response.result.isSuccess 
         { 
          let resJson = JSON(response.result.value!) 

          if isShowLoader == true 
          { 
           AppDelegate.getDelegate().dismissLoader() 
          } 

          success(resJson) 
         } 

         if response.result.isFailure 
         { 
          let error : Error = response.result.error! as Error 

          if isShowLoader == true 
          { 
           AppDelegate.getDelegate().dismissLoader() 
          } 

          failure(error) 
         } 

        } 
       case .failure(let encodingError): 
        if isShowLoader == true 
        { 
         AppDelegate.getDelegate().dismissLoader() 
        } 

        let error : NSError = encodingError as NSError 
        failure(error) 
       } 
      } 
     ) 
    } 
    else 
    { 
     CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!) 
    } 
} 
} 

================================== 

Appel Méthode

laisser aParams: [string: String] = [ "ReqCode": Constants.kRequestCodeLogin, "StoreDCID": strStoreID !, "CustEmail": dictAddLogin [AddLoginConstants.kEmail] !, "Mot de passe": dictAddLogin [ AddLoginConstants.kPassword] !, "DeviceID": "DeviceIDString", "DeviceType": "iOS",]

 WebServiceHelper.postWebServiceCall(Constants.BaseURL, params: aParams as [String : AnyObject]?, isShowLoader: true, success: { (responceObj) in 


      if "\(responceObj["RespCode"])" != "1" 
      { 
       let alert = UIAlertController(title: Constants.kAppName, message: "\(responceObj["RespMsg"])", preferredStyle: UIAlertControllerStyle.alert) 
       let OKAction = UIAlertAction(title: "OK", style: .default) { (action:UIAlertAction!) in 
       } 
       alert.addAction(OKAction) 
       self.present(alert, animated: true, completion: nil) 
      } 
      else 
      { 
       let aParams : [String : String] = [ 
        "Password" : self.dictAddLogin[AddLoginConstants.kPassword]!, 
        ] 
       CommonMethods.saveCustomObject(aParams as AnyObject?, key: Constants.kLoginData) 

      } 
      }, failure: 
      { (error) in 

       CommonMethods.showAlertWithError(Constants.kALERT_TITLE_Error, strMessage: error.localizedDescription,withTarget: (AppDelegate.getDelegate().window!.rootViewController)!) 
     }) 
    }