小编典典

将类型传递给通用Swift扩展,或理想地推断出它

swift

说你有

 class Fancy:UIView






    for v:UIView in superview!.subviews
        {
        if let f = v as? Fancy
            { f.hungry = false }
        }

因此,请尝试扩展

public extension UIView
    {
    internal func fancySiblings()->([Fancy])
        {
            return (self.superview!
                .subviews
                .filter { $0 != self }
                .flatMap { $0 as? Fancy }
                )
        }
    }

太好了,您现在可以

    for f:Fancy in self.fancySiblings()
        { f.hungry = false }

太棒了

但,

如何推广该扩展以与任何UIView子类型一起使用?

理想情况下,扩展甚至可以 推断类型 吗?以及采取类型?

所以,类似…

public extension UIView
    {
    internal func siblings<T>( something T )->([T])
        {
            return (self.superview!
                .subviews
                .filter { $0 != self }
                .flatMap { $0 as? T }
                )
        }

然后你可以这样称呼它…

    for f in self.siblings(Fancy)
    for p in self.siblings(Prancy)
    for b in self.siblings(UIButton)

您如何像这样“说明”一个通用扩展名?

看来您可以“向后推断”,

public extension UIView
    {
    internal func incredible<T>()->([T])
        {
        return (self.superview!
         .subviews
         .filter { $0 != self }
         .flatMap { $0 as? T }
         )
        }


    for f:Fancy in self.incredible()

    for p:Prancy in self.incredible()

太神奇了,但反过来却行不通。

你甚至可以…

    self.siblings().forEach{
        (f:Fancy) in
        d.hasRingOn = false
        }

因此,我仍然想知道如何“传递”类似的类型,forfinself.siblings(Fancy)并且理想情况下甚至可以推断出它。


阅读 246

收藏
2020-07-07

共1个答案

小编典典

只需使用.Type

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

之后for f in self.siblings(Fancy)应完全按预期工作。

完整的工作示例:

class Fancy : UIView {}

public extension UIView {
    internal func siblings<T>( _ : 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))

正确输出一个Fancy视图!


为了解决请求的添加,以便有选择地使用显式类型参数或使编译器的类型推断生效。您可以在同一扩展中创建第二个方法

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

这样,提供一个显式类型参数将调用方法一,而忽略该方法将需要您使其可推断,并将调用第二个函数,即内部调用第一个函数。


或者 ,您可以使用更 快捷的 方法,并在默认情况下使显式类型参数成为可选参数nil。值得注意的是,在省略类型参数的情况下,将强制进行推断:

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

这将使您可以通过以下方式调用方法

for f in self.siblings(Fancy)

甚至

for f : Fancy in self.siblings()

两者都可以工作,但仍只定义一个功能。

2020-07-07