Pass in a type to a generic Swift extension, or ideally infer it

后端 未结 2 1586
猫巷女王i
猫巷女王i 2020-12-03 03:26

Say you have

 class Fancy:UIView

you want to find all sibling Fancy views. No problem...

    for v:UIView in sup         


        
2条回答
  •  旧时难觅i
    2020-12-03 03:44

    Simply use the .Type:

    internal func siblings( something : T.Type)->([T]) {
        ...
    }
    

    Afterwards for f in self.siblings(Fancy) should work exactly as expected.

    Full working example:

    class Fancy : UIView {}
    
    public extension UIView {
        internal func siblings( _ : T.Type)->([T]) {
            return (self.superview!
                .subviews
                .filter { $0 != self }
                .flatMap { $0 as? T }
            )
        }
    }
    
    let superView = UIView()
    let view = UIView()
    superView.addSubview(view)
    superView.addSubview(UIView())
    superView.addSubview(Fancy())
    
    print(view.siblings(Fancy))
    

    Correctly outputs the one Fancy view!


    To address the requested addition for optionally using the explicit type parameter or take effect of the type inference of the compiler. You can create a second method in the same extension

    internal func siblings()->([T]) {
        return siblings(T)
    }
    

    That way providing a explicit type parameter calls method one, omitting it will require you to make it inferable and will call the second function which in terms calls the first one internally.


    Or, you can use the far more swifty way and make the explicit type argument an optional with default nil. That, remarkably, will force the inference in case of omitting the type argument:

    // power extension, it provides both infered or stated typing
    internal func siblings(_ : T.Type? = nil) -> ([T]) {
        return (self.superview!
            .subviews
            .filter { $0 != self }
            .flatMap { $0 as? T }
            )
    }
    

    That will enable you to call the method either via

    for f in self.siblings(Fancy)
    

    or even

    for f : Fancy in self.siblings()
    

    Both will work while still only defining one function.

提交回复
热议问题