将一个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。