Batch Requests

Batch Requests

Oftentimes you will need to request data from multiple endpoints for a view within your application, such as observations and advisories. While you can perform multiple requests using multiple endpoint service classes, it is often more efficient to get all necessary data in a single request.

The Xweather Weather API offers the batch request (opens in a new tab) for performing this action directly. Fortunately, the Xweather iOS SDK offers the AWFBatchRequest for the same functionality but with the ability to do so through the use of the same endpoint service classes you're already familiar with. This also eliminates the need for you to manage the batch request URL formatting or parsing to get the data you need.

Adding Endpoints

An AWFBatchRequest in the SDK is simply a series of individual endpoint service instances for each individual request. So to create a batch request, you first need to create instances for the individual endpoints you need to request data for:

let place = AWFPlace(city: "seattle", state: "wa", country: "us")
 
let obs = AWFObservations()
obs.options?.place = place
 
let forecasts = AWFForecasts()
forecasts.options?.place = place
forecasts.options?.limit = 7
forecasts.options?.filterString = "day"
 
let advisories = AWFAdvisories()
advisories.options?.place = place

Then create your batch request instance with the above endpoint objects:

let request = AWFBatchRequest(endpoints: [obs, forecasts, advisories])

Alternatively, you can create an empty batch request instance and add endpoints later:

let request = AWFBatchRequest()
request.addEndpoint(advisories)

If you need to add an endpoint that uses a specific API action, such as within (opens in a new tab) or search (opens in a new tab), you can either set the action property on the endpoint's options instance, or provide it when adding the endpoint to the batch request:

// setting the action on the options instance
advisories.options?.action = .search
 
// or, providing the action when adding to the request
request.addEndpoint(advisories, action: .search, options: nil)

You can also add individual endpoint instances to a batch request by associating them with a unique key. Using this method allows you to easily reference that endpoint and its results directly:

request.addEndpoint(advisories, forKey: "advisories")

The keyed endpoint method can also be used for specific actions:

request.addEndpoint(advisories, action: .search, forKey: "advisories", options: nil)

Once you've added an endpoint instance to a batch request by associating it with a key, you can retrieve that instance later:

let advisories = request.endpoint(forKey: "advisories")

Removing Endpoints

Similar to the methods support for adding endpoints to a batch request, you can also remove endpoints either by referencing the endpoint instance directly or using the key that was used when adding it:

// remove an endpoint by the instance
request.removeEndpoint(advisories)
 
// remove an endpoint by its key
request.removeEndpoint(forKey: "advisories")

You can also remove all endpoints from a batch request at once:

request.removeAllEndpoints()

Performing the Request

Once you're batch request is setup with the necessary endpoints instances and options, you're ready to perform the actual request:

request.get(withOptions: nil) { (request, error) in
    guard error == nil else {
        print("Batch request failed! \(error)")
        return
    }
 
    // return objects for a specific endpoint instance
    if let advisoryResults = request.results(for: advisories) as? [AWFAdvisory], advisoryResults.count > 0 {
        // do something with the data...
    }
 
    // or, return objects for an endpoint associated with a specific key
    if let advisoryResults = request.resultsForEndpoint(withKey: "advisories") as? [AWFAdvisory], advisoryResults.count > 0 {
        // do something with the data...
    }
}

As the example request above demonstrates, once the request has completed you can access the returned objects for each endpoint directly using either the resultsForEndpoint: or resultsForEndpointWithKey: methods on your request instance. These methods will always return an array of model objects associated with that endpoint, or nil if there were no results for that endpoint request.

Updating the Batch Request Place

If you are performing a batch request for a single location, you may need to set or change the location being used for all endpoint instances within the batch request. Instead of iterating through the array of endpoints or setting the location directly for each instance, you can update the place across all endpoints using setPlaceForAllLoaders::

request.setPlaceForAllEndpoints(AWFPlace(city: "houston", state: "tx", country: "us"))