我有一个自动布局便利功能,可以将视图堆叠在一起。对于我的间距参数,我想允许:
- 视图之间的间距为零
- 或单个
CGFloat
(所有视图均匀间隔( - 或
CGFloat
数组(视图之间的不同空格(
但是,我不确定如何定义这个参数。
// Ambiguous
func myconstrainer(_ views : [UIView], spacing : CGFloat = 0){}
func myconstrainer(_ views : [UIView], spacing : [CGFloat]? = nil){}
// Messy
func myconstrainer(_ views : [UIView], spacingA : CGFloat = 0, spacingB: [CGFloat]? = nil){}
您还可以尝试可变数量的参数,如下所示:
func myconstrainer(_ views: [UIView], spacing: CGFloat...) {
myconstrainer(views, spacing: spacing)
}
并提供一个简单的重载来处理数组:
func myconstrainer(_ views: [UIView], spacing: [CGFloat]) {
// Implementation...
}
因此,在使用偶数间距时,您无需将单个元素放在括号中。
呼叫站点:
myconstrainer([view1, view2, view3])
myconstrainer([view1, view2, view3], spacing: 123)
myconstrainer([view1, view2, view3], spacings: 1, 2, 3)
myconstrainer([view1, view2, view3], spacings: [1, 2, 3])
一些不明显的注意事项:
- 使用零参数调用
CGFloat...
可以很好地涵盖默认情况; - 而且,由于这个参数实际上是一个数组,我们可以将其转发到另一个不带括号的方法。
如果不诉诸泛型,这将带来一个(我认为不必要的(复杂性的世界,你就不能做你想做的事情,因为需要定义参数的类型才能从 Swift 旨在提供的类型安全中受益。
为什么不简单地将间距定义为CGFloats数组(如第二个声明(,如果spaceing.count == 1,则默认为第一种情况?
func myconstrainer(_ views : [UIView], spacing : [CGFloat]?) {
if spacing.count == 1 {
// all views spaced evenly code
}
else {
// different spaces between views code
}
}
PS(不需要将可选参数设置为 nil(
以下是我的做法:
func myconstrainer(_ views: [UIView], spacing: CGFloat) {
myconstrainer(views, spacings: repeatElement(spacing, count: views.count))
}
func myconstrainer<C: Collection>(_ views : [UIView], spacings: C)
where C.Iterator.Element == CGFloat {
// actual implementation...
}
呼叫站点:
myconstrainer([view1, view2, view3], spacing: 123.0)
myconstrainer([view1, view2, view3], spacings: [1, 2, 3])