将一个types传递给一个通用的Swift扩展,或者理想地推断它

说你有

class Fancy:UIView 

你想find所有兄弟Fancy意见。 没问题 …

  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子types?

理想情况下,扩展可以推断types ,甚至? 以及采取一个types?

所以,像…

 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) 

你怎么能“告诉”一个generics扩展的types使用,像这样?

看来你可以“倒退”,

 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 } 

所以我仍然想知道如何“传入”一个类似于for f in self.siblings(Fancy)的typesfor f in self.siblings(Fancy) ,理想上甚至可以推断它。

只需使用.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视图!


为了解决请求的添加,可选地使用显式types参数或者使编译器的types推断生效。 您可以使用相同的扩展名创build第二个方法

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

这样提供一个明确的types参数调用方法之一,省略它将需要你使其可驱动,并将调用第二个函数,在内部调用第一个函数。


或者 ,您可以使用更快速的方式,并使显式types参数为可选,默认nil 。 显然,在省略types参数的情况下会强制推断:

 // 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() 

两者都将工作,而仍然只定义一个function。

与之前所说的类似的答案,但更简单一些,不必传递任何东西或不止一次遍历子视图:

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

或者我偏好使用可选项:

 internal func siblings<T: UIView>() -> [T]? { return superview?.subviews.flatMap {return ($0 == self) ? nil : $0 as? T } } 

用法示例:

 class ExampleView: UIView { func getMatchingSiblings(){ let foundSiblings: [ExampleView] = siblings() } //or with the for loop in the question: for item: ExampleView in siblings() { } } 

处理generics时,只需要在方法的签名中使用genericstypes的一个实例。 所以如果你有一个参数,或者返回使用通用types的types,你不需要传递这个types。

Interesting Posts