Do you need help on a specific subject? Use the contact form (Request a blog entry) on the right hand side.

2015-02-11

Swift extensions: Array function removeObject

I have several instances in my Objective-C code that use the "removeObject" operation on a NSMutableArray.
In Swift, the Array type only offers us removeAtIndex, removeAll, removeLast and removeRange. No removeObject anymore.

But Swift does allow type extensions, thus we can implement it ourselves. My first attempt was this:

extension Array {
    
    mutating func removeObject(object: T) -> T? {
        if count > 0 {
            for index in startIndex ..< endIndex {
                if self[index] === object { return self.removeAtIndex(index) }
            }
        }
        return nil
    }

}

But that does not work, it generates an error: Type 'T' does not conform to protocol 'AnyObject'

Hmm. So that is the reason why 'removeObject' no longer exists. The generic item used in the array does not implement AnyObject. As you may recall 'AnyObject' is only available for class types, whereas 'Any' can be used for any type at all.

Since 'Array' can be instantiated with 'Any' type, the '===' operator is not available. This operator compares only references, and 'Any' type objects are not guaranteed to use references.

So if we want to implement a 'removeObject' then we must introduce an additional constraint on the type to be used. Like this:

extension Array {
    
    mutating func removeObject<U: AnyObject>(object: U) -> T? {
        if count > 0 {
            for index in startIndex ..< endIndex {
                if (self[index] as! U) === object { return self.removeAtIndex(index) }
            }
        }
        return nil
    }
}

Type checking in Swift enforces that the type the array is called for is of the same type as the type the array was instantiated for. Hence the cast 'as U' is safe.

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

No comments:

Post a Comment