1

Morning all, I've been following along the examples in the excellent iOS Apps With REST APIs book and as a result using Alamofire and SwiftyJSON. One thing I don't see mentioned in the book is how you would sort the incoming json objects into a specific order, eg. date. The code I've pasted below works fine for pulling in the json objects however as far as I can tell, they're automatically ordered by created_by. I'd like to sort by a different order, lets say my class was called Vegetable and had a name attribute so that I could sort by something like:

.sort { $0.name < $1.name }

I'll start with the Vegetable class in Vegetable.swift

class Vegetable: ResponseJSONObjectSerializable {
    var id: Int?
    var name : String?
    var date: NSDate?
}

Inside my JSONSerializer file I have the following, I'm not sure I'd wish to change the order directly in here as I'd prefer some more flexibility with each call.

    public func responseArray<T: ResponseJSONObjectSerializable>(completionHandler: Response<[T], NSError> -> Void) -> Self {
    let serializer = ResponseSerializer<[T], NSError> { request, response, data, error in
        guard error == nil else {
            return .Failure(error!)
        }
        guard let responseData = data else {
            let failureReason = "Array could not be serialized because input data was nil."
            let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
            return .Failure(error)
        }

        let JSONResponseSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
        let result = JSONResponseSerializer.serializeResponse(request, response, responseData, error)

        switch result {
        case .Success(let value):
            let json = SwiftyJSON.JSON(value)

            var objects: [T] = []
            for (_, item) in json {
                if let object = T(json: item) {
                    objects.append(object)
                }
            }
            return .Success(objects)
        case .Failure(let error):
            return .Failure(error)
        }
    }

    return response(responseSerializer: serializer, completionHandler: completionHandler)
}

Then, in my APIManager I have the following function

func getAllVegetables(completionHandler: (Result<[Vegetable], NSError>) -> Void) {
    Alamofire.request(VegetableRouter.GetVegetables())
        .responseArray { (response:Response<[Vegetable], NSError>) in
            completionHandler(response.result)
    }
}

Finally, populate my tableview I have:

func loadVegetables() {
    self.isLoading = true
    VegetablesAPIManager.sharedInstance.getAllVegetables() {
        result in
        self.isLoading = false
        if self.refreshControl.refreshing {
            self.refreshControl.endRefreshing()
        }

        guard result.error == nil else {
            print(result.error)
            // TODO: Display Error
            return
        }
        if let fetchedVegetables = result.value {
            self.vegetables = fetchedVegetables
            for vegetable in fetchedVegetables {
                // Nothing here at the moment
            }
        }

        self.tableView.reloadData() 
    }

}

I appreciate any help I can get with this, Thanks!

2
  • Do you have a NSDate property in your Vegetable class ? Commented Apr 9, 2016 at 12:13
  • Yep, I just added a simple class to my question for clarity. Commented Apr 9, 2016 at 12:18

1 Answer 1

4

Since you have a NSDate property, you can sort with the compare method of NSDate.

let sorted = result.value.sort { $0.date.compare($1.date) == .OrderedAscending }
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, Which file would i be looking to add that?
Inside loadVegetables() method, right before you add the result to your tableView datasource and reload your tableView.
When I try that I get the following error: Value of type 'Result<[Vegetable], NSError>' (aka 'Result<Array<Vegetable>, NSError>') has no member 'sortInPlace'. and if I try to call sortInPlace on the results.value! I get Value is get-only property.
Ah, I got it, so in loadVegetables() I did self.vegetables.sortInPlace { $0.date!.compare($1.date!) == .OrderedDescending } and it works! Many thanks for your help, I'll mark this as answered.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.