evermeer / AlamofireJsonToObjects

An Alamofire extension which converts JSON response data into swift objects using EVReflection
Other
161 stars 28 forks source link

Null response in array #13

Closed MohsinN closed 8 years ago

MohsinN commented 8 years ago

In the example you mentioned, the array for "three_day_forecast' returns 0. Please look into it.

Cheers, Mohsin

evermeer commented 8 years ago

Did you run the unit tests for this? When I run the tests they all succeed. In my case it returns 3 items for the forecast. To be sure I added an extra check for the number of items. See: https://github.com/evermeer/AlamofireJsonToObjects/blob/daefd3d0fa03ea39e36c1619f8a773136b2064ed/AlamofireJsonToObjectsTests/AlamofireJsonToObjectsTests.swift#L52

MohsinN commented 8 years ago

Here is the sample code i used to verify. The response returns the correct the json but "result.three_day_forecast.count" returns zero.

  func testResponseObject() {
    let URL = "https://raw.githubusercontent.com/evermeer/AlamofireJsonToObjects/master/AlamofireJsonToObjectsTests/sample_json"
    Alamofire.request(.GET, URL)

      .responseJSON { response in
        // do whatever you want here
        switch response.result {
        case .Failure(let error):
          print(error)
        case .Success(let responseObject):
          print(responseObject)
        }
      }

      .responseObject { (response: Result<WeatherResponse, NSError>) in
        switch response {
        case .Success(let JSON):
        print("Success with JSON: \(JSON)")
        if let result = response.value {

          print(result.three_day_forecast.count)
          // That was all... You now have a WeatherResponse object with data
          }

        case .Failure(let error):
        print("Request failed with error: \(error)")
        }

    }

  }
evermeer commented 8 years ago

The call is an asynchronous operation. When running it from a unit test you have to add some code to wait for the result. The function would then look like this:


    func testResponseObjectX() {
        let URL = "https://raw.githubusercontent.com/evermeer/AlamofireJsonToObjects/master/AlamofireJsonToObjectsTests/sample_json"
        let expectation = expectationWithDescription("\(URL)")

        Alamofire.request(.GET, URL)
            .responseJSON { response in
                // do whatever you want here
                switch response.result {
                case .Failure(let error):
                    print(error)
                case .Success(let responseObject):
                    print(responseObject)
                }
            }

            .responseObject { (response: Result<WeatherResponse, NSError>) in
                switch response {
                case .Success(let JSON):
                    print("Success with JSON: \(JSON)")
                    if let result = response.value {

                        print(result.three_day_forecast.count)
                        // That was all... You now have a WeatherResponse object with data
                    }

                case .Failure(let error):
                    print("Request failed with error: \(error)")
                }
                expectation.fulfill()
        }
        waitForExpectationsWithTimeout(10, handler: { (error: NSError?) -> Void in
            XCTAssertNil(error, "\(error)")
        })

    }
MohsinN commented 8 years ago

Thanks, much appreciated. I am new to swift 2, any advice?

evermeer commented 8 years ago

Well, just look at a lot of code from others.

When considering the code above: You have to be aware that async operations are executed in the background. If you get the response and want to update the user interface, you have to execute the call on the main queue.

sagits commented 8 years ago

Hi, i have the same issue trying to parse a single object. But my code is on production, does alamofireJsonToObjects automatically handles the async request? My json is there, i can debug the parser and it works but on the responseObject the response is null. Im doing the request just like the example above, but without the waitForExpectation. Can you help me please?

evermeer commented 8 years ago

@sagits It would help if you could share some code. Also look in the output window to see if there are any warnings or errors.

All Alamofire calls are asynchronous. You will not be sure when the responseObject block is executed. So you can't return a value. You could call another function that was passed on as a parameter.

sagits commented 8 years ago

It was a mistake. I through that the object already comes populated before the .Success, after using .Success everything went fine. Thank you.

By the way, whats the pattern behind this approach? Why not make .Success and .Error internal and return only the response object? Thanks in advance.

evermeer commented 8 years ago

Well, you don't have to use the .Sucess. Of course its good that you also have code for reacting on a failure. You could also just use the response.value as you can see in the sample code on the readme.md. Below you can see the minimal code what's required:

Alamofire.request(.GET, URL)
           .responseObject { (response: Result<WeatherResponse, NSError>) in
           if let result = response.value {
               // That was all... You now have a WeatherResponse object with data
           }
        }