AFNetworking and Swift - Save json response

2019-03-30 18:22发布

问题:

I want to make a GET request in swift to get some Json data. I tried to use AFNetworking and it works, but I don't know how to return the Json I get.

I tried with a return but it's made before the GET so I get nothing...

func makeGet(place:String) -> String
{
    var str:String = ""
    let manager = AFHTTPRequestOperationManager()
    manager.requestSerializer.setValue("608c6c08443c6d933576b90966b727358d0066b4", forHTTPHeaderField: "X-Auth-Token")
    manager.GET("http://something.com/api/\(place)",
        parameters: nil,
        success: { (operation: AFHTTPRequestOperation!,responseObject: AnyObject!) in
            str = "JSON:  \(responseObject.description)"
            println(str) //print the good thing
        },
        failure: { (operation: AFHTTPRequestOperation!,error: NSError!) in
            str = "Error: \(error.localizedDescription)"
        })
    return str //return ""
}

Can you help me ?

回答1:

You're not getting a response from that function, because the GET operation happens asynchronously. That is, the order of execution looks like this:

  1. You call makeGet

  2. makeGet creates manager, which fires off a GET request

  3. makeGet finishes executing and returns an empty string

  4. (some time later) manager receives a value back from the server and executes either the success or failure block.

So the only time you have access to the JSON that comes back from the server is in step 4, and you need to find a way of storing that value so you can parse it or use it or whatever. There are a variety of options here -- one is to define closures that call event handlers on your class instance, like this:

class MyClass {

    func jsonLoaded(json: String) {
        println("JSON: \(json)")
    }

    func jsonFailed(error: NSError) {
        println("Error: \(error.localizedDescription)")
    }

    func makeGet(place:String) {        
        let manager = AFHTTPRequestOperationManager()
        manager.requestSerializer.setValue("608c6c08443c6d933576b90966b727358d0066b4", forHTTPHeaderField: "X-Auth-Token")
        manager.GET("http://something.com/api/\(place)",
            parameters: nil,
            success: { (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) in
                self.jsonLoaded(responseObject.description)
            },
            failure: { (operation: AFHTTPRequestOperation!, error: NSError!) in
                self.jsonFailed(error)
            }
        )
    }

}


回答2:

Since you want to return the value after the webservice request is completed you have to pass the data via a delegate or a block(In swift it is called closures)

I see blocks useful here

//Above your class file create a handler alias 
typealias SomeHandler = (String! , Bool!) -> Void

func makeGet(place:String , completionHandler: SomeHandler!)
{
    var str:String = ""
    let manager = AFHTTPRequestOperationManager()
    manager.requestSerializer.setValue("608c6c08443c6d933576b90966b727358d0066b4", forHTTPHeaderField: "X-Auth-Token")
    manager.GET("http://something.com/api/\(place)",
        parameters: nil,
        success: { (operation: AFHTTPRequestOperation!,responseObject: AnyObject!) in
            str = "JSON:  \(responseObject.description)"
            println(str) //print the good thing
            completionHandler(str,false)   //str as response json, false as error value

        },
        failure: { (operation: AFHTTPRequestOperation!,error: NSError!) in
            str = "Error: \(error.localizedDescription)"
            completionHandler("Error",true)   
        })
    //return str //return ""    You don't want to return anything here
}

When you want to call the method get the values like this

makeGet(){
   yourJSONString , errorValue in   //Here the value will be passed after you get the response

     if !errorValue { 
         println("The End."
     }
}

More about swift closures

FYI: AFNetworking owner has created a new Networking layer for swift and it is called Alamofire (AF from AFNetworking is Alamofire :])



回答3:

let manager = AFHTTPSessionManager()
    manager.GET("http://api.androidhive.info/json/movies.json", parameters: nil, success: { (operation, responseObject) -> Void in
        print(responseObject)
        }, failure: nil)

AFHTTPRequestOperationManager is not available in latest AFnetworking library, it has replaced with AFHTTPSessionManager. This is a simple example of getting response object.