Cree una extensión de matriz rápida para una matriz tipeada

Esta pregunta ( Crear extensión de matriz rápida para matrices mecanografiadas [duplicado] ) está muy cerca de responder la pregunta, pero lo que se hace dentro de esta pregunta puede ser genérico.

Esta pregunta ( ¿Cómo puedo extender matrices tipeadas en Swift? ) También se acerca pero no es la misma pregunta debido al ejemplo que no restringe la extensión a un tipo particular de matriz.

Di que tengo una matriz de UIView .

 [node, node1, node2] 

Y quiero agregarle una func extension como:

 [node, node1, node2].hideAll() extension UIView { func hide() { self.hidden = true } } extension Array { func hideAll() { for node in self { (node as! UIView).hide() } } } 

No quiero que se hideAll() en cualquier cosa que no sea una matriz que contenga objects de tipo UIView . ¿Puedo y cómo restrinjo esto?

Puedes probar algo como:

 protocol ShyObject : AnyObject { var hidden: Bool { get set } } extension SequenceType where Generator.Element : ShyObject { func hideAll() { for e in self { e.hidden = true } } func showAll() { for e in self { e.hidden = false } } } import UIKit extension UIView : ShyObject {} // TODO: extend more shy types... let nodes = Array(count: 5, repeatedValue: UIView()) nodes.hideAll() 

Si específicamente necesitas el método hide() también, puedes proporcionarlo genéricamente para todos los ShyObject s:

 extension ShyObject { func hide() { hidden = true } func show() { hidden = false } } 

Y para implementar la conformidad para un tipo que no tiene hidden :

 class MyClass {} extension MyClass : ShyObject { var hidden: Bool { get { return /* true or */ false } set { /* hide me or show me */ } } } let myObjects = Array(count: 5, repeatedValue: MyClass()) myObjects.hideAll() 

También podemos tener properties allHidden y allShown también:

 extension SequenceType where Generator.Element : ShyObject { var allShown: Bool { return !contains{ $0.hidden == true } } var allHidden: Bool { return !contains{ $0.hidden == false } } } extension MutableCollectionType where Generator.Element : ShyObject { var allShown: Bool { get { return !contains{ $0.hidden == true } } set { newValue ? showAll() : hideAll() } } var allHidden: Bool { get { return !contains{ $0.hidden == false } } set { newValue ? hideAll() : showAll() } } } var nodes = Array(count: 5, repeatedValue: UIView()) // note the `var` :( nodes.allShown = false nodes.allHidden // true (does not in itself require a mutable collection!) 

… que funciona, pero tiene un gran inconveniente de que la secuencia tiene que ser mutable si queremos usar un setter. Esto se debe a que el comstackdor asume que todas las properties computadas con un setter están mutating incluso cuando los elementos de secuencia son de tipo de reference como aquí … Sin embargo, al less allShown allHidden properties de allShown y allHidden sin pagar con mutabilidad .

Tenga en count que, como comentó @dfri en un punto, esta respuesta es más general de lo que la pregunta explícitamente requiere. Si esto no se desea, @dfri sugiere:

 protocol Hideable { func hide() } extension UIView : Hideable { func hide() { self.hidden = true } } extension Array where Element: Hideable { func hideAll() { for e in self { e.hide() } } }