This is my method when I sort elements by position
property. Both DBSet
and DBItem
have that property.
@objc(DBCategory)
class DBCategory: NSManagedObject {
@NSManaged var identifier: String
@NSManaged var items: Set<DBItem>
@NSManaged var sets: Set<DBSet>
}
And this is how I use it
private var elements = [AnyObject]()
private func prepareElements() {
elements.removeAll(keepCapacity: false)
if let items = currentCategory?.items {
for item in items {
elements.append(item)
}
}
if let sets = currentCategory?.sets {
for set in sets {
elements.append(set)
}
}
elements.sort {
var previousPosition = 0
var currentPosition = 0
if let set = $0 as? DBSet {
previousPosition = Int(set.position)
}
if let item = $0 as? DBItem {
previousPosition = Int(item.position)
}
if let set = $1 as? DBSet {
currentPosition = Int(set.position)
}
if let item = $1 as? DBItem {
currentPosition = Int(item.position)
}
return previousPosition < currentPosition
}
}
position
is type of Int16
How can I simplify that?
Create a protocol that defines your position property. Let's call it HasPosition. Declare an array of [HasPosition]. You can then sort the array directly with any of the standard sorting functions.
If .position
returns the same type in both cases, and that type is comparable, you can simplify that to the following:
elements.sort {
let l = ($0 as? DBSet)?.position ?? ($0 as? DBItem)?.position
let r = ($1 as? DBSet)?.position ?? ($1 as? DBItem)?.position
return l < r
}
The key to this working is that there is a version of <
that works for optionals, where nil
is defined as less than any non-nil value. So values in the array not of one of the two types will be sorted to the beginning.
When you have the array as [AnyObject]
and the position
is Int16
, this should works:
elements.sort {
($0.position as Int16?) < ($1.position as Int16?)
}
This works because AnyObject
has any @objc
properties as Optional
.
Demo:
class DBItem:NSObject {
var position:Int16
init(position: Int16) { self.position = position }
override var description:String { return "DBItem(\(position))" }
}
class DBSet:NSObject {
var position:Int16
init(position: Int16) { self.position = position }
override var description:String { return "DBSet(\(position))" }
}
var elements:[AnyObject] = [
DBItem(position: 5),
DBSet(position: 2),
DBItem(position: 42),
DBSet(position: 62),
DBSet(position: 21),
DBItem(position: 6),
DBSet(position: 36),
DBItem(position: 24),
]
elements.sort {
($0.position as Int16?) < ($1.position as Int16?)
}
println(elements)
// -> [DBSet(2), DBItem(5), DBItem(6), DBSet(21), DBItem(24), DBSet(36), DBItem(42), DBSet(62)]
And your prepareElements()
can be simplified as:
private func prepareElements() {
elements = []
if let ct = currentCategory {
elements += Array(ct.items) as [AnyObject]
elements += Array(ct.sets) as [AnyObject]
elements.sort {
($0.position as Int16?) < ($1.position as Int16?)
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.