这个问题(Create swift array extension for typed arrays [duplicate])非常接近回答这个问题,但在这个问题中做的事情可能是通用的。
这个问题(How can I extend typed Arrays in Swift?)也接近但问题不同,因为这个例子没有限制扩展到特定类型的数组。
假设我有一个UIView
数组。
[node, node1, node2]
我想在其中添加extension
func
,如:
[node, node1, node2].hideAll()
extension UIView {
func hide() { self.hidden = true }
}
extension Array {
func hideAll() {
for node in self { (node as! UIView).hide() }
}
}
除了包含hideAll()
类型对象的数组外,我不希望访问UIView
。我可以和我如何限制这个?
答案 0 :(得分:1)
您可以尝试以下内容:
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()
如果您还特别需要hide()
方法,则可以为所有ShyObject
提供通用:
extension ShyObject {
func hide() { hidden = true }
func show() { hidden = false }
}
为没有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()
我们也可以拥有allHidden
和allShown
属性:
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!)
...哪个有效,但它有一个主要的缺点,如果我们想使用一个setter,序列必须是可变的。这是因为所有带有setter的计算属性都被编译器假设为mutating
,即使序列元素属于这里的引用类型......但是,我们至少可以只有getter allShown
和allHidden
属性,但没有为其付出可变性。
请注意,正如@dfri在某一点上所评论的那样,这个答案比明确要求的问题更为通用。如果不需要,@ dfri建议:
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() } }
}