Swift: Сортировка массива по дескрипторам сортировки
Я использую coredata, поэтому мне нужны дескрипторы сортировки для моих сущностей
Например, объект Coordinate имеет этот класс func:
class func sortDescriptors() -> Array<NSSortDescriptor>
{
return [NSSortDescriptor(key: "sequence", ascending: true)]
}
Я использую это при выполнении запросов на выборку в CoreData следующим образом:
var request = NSFetchRequest(entityName: entityName)
request.sortDescriptors = T.sortDescriptors()
Однако, когда у меня есть массив координат как свойство на другом объекте coredata, это NSSet (I.e. unsorted)
Чтобы решить эту проблему, я возвращаю координаты следующим образом:
return NSArray(array: coordinates!).sortedArrayUsingDescriptors(Coordinate.sortDescriptors()) as? Array<Coordinate>
Что кажется уродливым, чтобы использовать NSArray только для того, чтобы получить метод sortedArrayUsingDescriptors
. Есть ли аналогичный способ сделать это непосредственно на Swift-массиве, I.e. Array<Coordinate>
с помощью дескрипторов сортировки?
Спасибо!
Ответы
Ответ 1
Для этого нет встроенного метода, но вы можете добавить их с помощью расширения протокола:
extension MutableCollectionType where Index : RandomAccessIndexType, Generator.Element : AnyObject {
/// Sort `self` in-place using criteria stored in a NSSortDescriptors array
public mutating func sortInPlace(sortDescriptors theSortDescs: [NSSortDescriptor]) {
sortInPlace {
for sortDesc in theSortDescs {
switch sortDesc.compareObject($0, toObject: $1) {
case .OrderedAscending: return true
case .OrderedDescending: return false
case .OrderedSame: continue
}
}
return false
}
}
}
extension SequenceType where Generator.Element : AnyObject {
/// Return an `Array` containing the sorted elements of `source`
/// using criteria stored in a NSSortDescriptors array.
@warn_unused_result
public func sort(sortDescriptors theSortDescs: [NSSortDescriptor]) -> [Self.Generator.Element] {
return sort {
for sortDesc in theSortDescs {
switch sortDesc.compareObject($0, toObject: $1) {
case .OrderedAscending: return true
case .OrderedDescending: return false
case .OrderedSame: continue
}
}
return false
}
}
}
Но обратите внимание, что это будет работать только тогда, когда элементы массива являются классами, а не структурами, поскольку метод NSSortDescriptor compareObject требует аргументов, соответствующих AnyObject
Ответ 2
Другим подходом к хорошим расширениям Damien может быть мультилитный.
myArray = (myArray as NSArray).sortedArrayUsingDescriptors(tableView.sortDescriptors) as! Array
Исходный источник: NSHipster
Ответ 3
Swift 3 Версия ответа @Darniel
extension MutableCollection where Self : RandomAccessCollection {
/// Sort `self` in-place using criteria stored in a NSSortDescriptors array
public mutating func sort(sortDescriptors theSortDescs: [NSSortDescriptor]) {
sort { by:
for sortDesc in theSortDescs {
switch sortDesc.compare($0, to: $1) {
case .orderedAscending: return true
case .orderedDescending: return false
case .orderedSame: continue
}
}
return false
}
}
}
extension Sequence where Iterator.Element : AnyObject {
/// Return an `Array` containing the sorted elements of `source`
/// using criteria stored in a NSSortDescriptors array.
public func sorted(sortDescriptors theSortDescs: [NSSortDescriptor]) -> [Self.Iterator.Element] {
return sorted {
for sortDesc in theSortDescs {
switch sortDesc.compare($0, to: $1) {
case .orderedAscending: return true
case .orderedDescending: return false
case .orderedSame: continue
}
}
return false
}
}
}