Swift:使用排序描述符对数组进行排序

18
我正在使用CoreData,所以我需要对实体进行排序描述符。
例如,Coordinate实体具有以下类功能:
class func sortDescriptors() -> Array<NSSortDescriptor>
{
    return [NSSortDescriptor(key: "sequence", ascending: true)]
}

我在执行像这样的fetch请求到CoreData时使用它:

var request = NSFetchRequest(entityName: entityName)

request.sortDescriptors = T.sortDescriptors()

然而,当我在另一个 CoreData 对象的属性中有一组坐标数组时,它是一个 NSSet (即未排序的)。

为了解决这个问题,我会像下面这样返回坐标:

return NSArray(array: coordinates!).sortedArrayUsingDescriptors(Coordinate.sortDescriptors()) as? Array<Coordinate>

使用NSArray仅仅为了调用sortedArrayUsingDescriptors方法感觉很丑陋。是否有一种类似的方法可以直接在Swift数组(如Array<Coordinate>)上使用排序描述符进行排序?

谢谢!


1
为什么不使用 NSSetsortedArrayUsingDescriptors() 方法呢? - rintaro
我也可以这样做!但问题仍然存在:排序描述符是否与Swift数组兼容? - ullstrm
@rintaro,根据定义,NSSet实例是无序的。我猜你是指的是NSArray - Bart Jacobs
3个回答

20

达米安的优秀扩展的另一种方法可能是多播。

myArray = (myArray as NSArray).sortedArrayUsingDescriptors(tableView.sortDescriptors) as! Array

原始来源:NSHipster


10

没有内置的方法可以做到这一点,但是你可以使用协议扩展来添加它们:

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。


非常感谢你!这对我来说是一个令人头疼的问题。感谢你帮助我解决了它。 - Tobonaut

7

@Darniel的答案的Swift 3版本:

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
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接