1

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?

2
  • Can you Also show the declaration of your two object types? (DBSet and DBItem) Commented May 29, 2015 at 11:51
  • They are from Core Data... Commented May 29, 2015 at 11:52

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

This has a big downside of type erasure…
Though, I guess the types are thoroughly erased in whatever he has here at the moment...
Wouldn't elements have to be type [AnyObject] in order to contain multiple types? Explain how my solution loses information? (Not being snide... You know more about Swift than I)
Yeah it’s hard to say since we don’t see the declaration of elements.
1

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.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.