RileyDev
RileyDev

Reputation: 2515

Sorting data by multiple key values

I have a basic list app with two entities Folder and Item with a to many relationship, the folder subclass has a function called itemsArray() which returns the Items in a sorted array by creationDate which are displayed UITableView.

Item has two properties called date of type NSDate and another of type bool called completed. I have created a function where I can mark the cell item object as completed which changes the cell text color to grey.

Is there a way I can also sort it by its completed value ? For e.g the completed value of true or false should separate all the completed items and then also sort it by the creationDate.

The end result should be where the completed items are at the bottom of the UITableView and in order of date as well as the non completed items are in order of date. As if completion is higher priority than the date but still orders by creationDate

Heres my current function with sort descriptor to return an array;

func itemsArray() -> [Item] {
    let sortDescriptor = NSSortDescriptor(key: "creationDate", ascending: true)
    return checklist.sortedArrayUsingDescriptors([sortDescriptor]) as! [Item]
}

PS: I tried some work arounds such as when marking as completed updating the date so it is at the bottom. This separates the completed items with the non completed. But when unmarking the item it remains at the bottom also this isn't a good long term solution as I may want to change the sorting to alphabetical order and completion.

Upvotes: 1

Views: 2172

Answers (1)

Code Different
Code Different

Reputation: 93141

You can add another NSSortDescriptor to the function:

func itemsArray() -> [Item] {
    let sortByCompleted = NSSortDescriptor(key: "completed", ascending: true)
    let sortByCreationDate = NSSortDescriptor(key: "creationDate", ascending: true)
    return checklist.sortedArrayUsingDescriptors([sortByCompleted, sortByCreationDate]) as! [Item]
}

Play with the ascending value to get true first or false first. Or the Swifty way of doing things:

func itemsArray() -> [Item] {
    return checklist.sort {
        if $0.completed == $1.completed {
            return $0.creationDate < $1.creationDate
        }
        return $0.completed < $1.completed
    }
}

Upvotes: 3

Related Questions