user1007522 user1007522 - 3 months ago 200
Swift Question

Inheritance from non-protocol, non-class Type

I want an extension on a Array where you can find an item that is of some type.

I tried like this:

func findItem<U: Type>(itemToFind: U) -> AnyObject? {
for item in self {
if let obj = item as? itemToFind {
return obj
}
}
return nil
}


So I check if it is the same type and then I want to return the obj.

The error I get is:


Inheritance from non-protocol, non-class 'Type'.


How can I fix this that I can pass to the function
ViewController.self
and that I get back nil if not found or the viewcontroller that is in the array?

Answer

The syntax <U: Type> in this context means you're declaring a new generic placeholder U in your function signature, which inherits from (in the case of classes), or conforms to (in the case of protocols) Type.

As Type is neither a protocol nor class, I assume what you really want is an unconstrained generic placeholder, and instead want to pass in a given type as an argument to the function, which will define the type of U.

In this case, you'll want to use the metatype U.Type as the function input type (as well as U? for the function return type – as the return type will be the optional type of whatever type you pass into the function). For example:

extension Array {
    func firstElement<U>(ofType _: U.Type) -> U? {
        for element in self {
            if let element = element as? U {
                return element
            }
        }
        return nil
    }
}

let array : [Any] = [2, "bar", 3, "foo"]
print(array.firstElement(ofType: String.self)) // Optional("bar")

As a side note, this could be simplified slightly by using pattern matching in the for loop:

func firstElement<U>(ofType _: U.Type) -> U? {
    for case let element as U in self {
        return element
    }
    return nil
}