简体   繁体   中英

Handle JSON Response with Alamofire in Swift

sorry for my bad english :)

I have a problem to parse JSON response over Alamofire in Swift for an iOS app. I wrote a function to return a string of JSON response. The request and response handling I do with Alamofire and the JSON handling I do with SwiftyJSON . At the begin I declare a var called jsonString with the value test . Then I do a request to an REST Service and get a JSON response by clicking a button. This response I want to return with the function ping(url:String) . At the end I print the returned response as a test. But on the first click on the button the return value from ping is test and not the JSON string of the response. On the second click on the button I get the right return value. Why I have this problem. Is the Alamofire request an asynchronous operation? I want to wait for the response. How can I solve the problem to get the right value on first click and not test as value?

Here is my 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)}

In the first click, the code

return self.jsonString

will run before

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

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

you will get nil form the self.jsonString in the first time, you second click will get the first click's request data.

If you use SwiftyJSON and Alamofire you can try Alamofire-SwiftyJSON

You could also try running

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

The problem you are having is that you are trying to return the result of an asynchronous method synchronously.

You have two solutions:

  1. Return the result asynchronously
  2. Wait for the asynchronous call to complete

I've written a response to this very same question a few minutes ago on this thread, I'll suggest you check it out: https://stackoverflow.com/a/33130512/422288

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

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

Call Method

let aParams : [String : String] = [ "ReqCode" : Constants.kRequestCodeLogin, "StoreDCID" : strStoreID!, "CustEmail" : dictAddLogin[AddLoginConstants.kEmail]!, "Password" : 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)!)
        })
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM