If this will be the default and most prevalent way you want want to sort customers by I'd approach this by defining Comparable for the customer to take into account these priorities.
extension Customer: Comparable {
static func < (lhs: Customer, rhs: Customer) -> Bool {
switch (lhs.hasPurchased, rhs.hasPurchased) {
case (true, true): return lhs.purchaseDate! < rhs.purchaseDate!
case (true, false): return false
case (false, true): return true
case (false, false): return lhs.name < rhs.name
}
}
}
This will then allow you to just use the .sorted() method from Sequence:
customers.sorted()
As an examples of this:
let customers:[Customer] = [
Customer(name: "Alan", hasPurchased: false, purchaseDate: nil),
Customer(name: "Ben", hasPurchased: false, purchaseDate: nil),
Customer(name: "Carol", hasPurchased: true, purchaseDate: Date()),
Customer(name: "Dan", hasPurchased: true, purchaseDate: Date().addingTimeInterval(100)),
Customer(name: "Elsie", hasPurchased: false, purchaseDate: nil),
Customer(name: "Frank", hasPurchased: true, purchaseDate: Date().addingTimeInterval(200))
]
let s = customers.sorted()
s.map{print($0)}
Which gives you:
Customer(name: "Alan", hasPurchased: false, purchaseDate: nil)
Customer(name: "Ben", hasPurchased: false, purchaseDate: nil)
Customer(name: "Elsie", hasPurchased: false, purchaseDate: nil)
Customer(name: "Carol", hasPurchased: true, purchaseDate: Optional(2021-08-09 11:02:55 +0000))
Customer(name: "Dan", hasPurchased: true, purchaseDate: Optional(2021-08-09 11:04:35 +0000))
Customer(name: "Frank", hasPurchased: true, purchaseDate: Optional(2021-08-09 11:06:15 +0000))
This approach will mean that if you want at some other point, for example, to just sort by name, then you will have to define that sort explicitly via a closure, but as that sort closure will be far simpler to write (and later on to understand) I see this as an acceptable compromise. It depends on the detail of your wider use case, which isn't clear from the question. If this need is the exception rather than the norm, you can adopt the above approach to an explicit sort closure.
if, use plainif, withelseetc, or it will be unreadable. It should be easier then, because you have already the logic..