简体   繁体   English

在Swift中使用Alamofire处理JSON响应

[英]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. 我在iOS应用程序的Swift中通过Alamofire解析JSON响应时遇到问题。 I wrote a function to return a string of JSON response. 我编写了一个函数来返回JSON响应字符串。 The request and response handling I do with Alamofire and the JSON handling I do with SwiftyJSON . 请求和响应处理我做Alamofire和JSON处理我做SwiftyJSON At the begin I declare a var called jsonString with the value test . 首先,我声明一个名为jsonString的变量 ,其值为test Then I do a request to an REST Service and get a JSON response by clicking a button. 然后,我向REST服务发出请求,并通过单击按钮获得JSON响应。 This response I want to return with the function ping(url:String) . 我想使用函数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. 但是,在第一次单击按钮时,从ping返回的值是test而不是响应的JSON字符串。 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? Alamofire是否请求异步操作? 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. 您将在第一时间从self.jsonString获得nil,第二次单击将获得第一次单击的请求数据。

If you use SwiftyJSON and Alamofire you can try Alamofire-SwiftyJSON 如果您使用SwiftyJSON和Alamofire,则可以尝试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 几分钟前,我已经在此线程上对这个相同的问题写了一个回复,我建议您检查一下: 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", ] 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)!)
        })
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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