我在UIView上有一个扩展,它根据元类型返回一个子视图数组。这样我可以查询视图层次结构,例如所有UITextFields等。
extension UIView {
func subviewsOfType<T:UIView>(_:T.Type) -> [T]? {
...
}
}
这可以像这样调用:
let fields = loginView.subviewsOfType(UITextField.self)
现在,我想在该数组[UITextField]
上使用与传入的泛型相匹配的接口,换句话说,在UITextField上可用的任何内容,例如:
fields.alpha = 0.3 // via UIView
fields.enabled = false // via UIControl
我在MutableCollectionType
上创建了扩展程序以提供这些替换:
extension MutableCollectionType where Generator.Element == UIView {
var alpha:CGFloat {
get {
if let first = self.first {
return first.alpha
} else {
return 1.0
}
}
set {
for view in self {
view.alpha = newValue
}
}
}
}
extension MutableCollectionType where Generator.Element == UIControl {
var enabled:Bool {
get {
if let first = self.first {
return first.enabled
} else {
return true
}
}
set {
for view in self {
view.enabled = newValue
}
}
}
}
但是,当我尝试使用这些扩展时,它们无法按预期工作。 :(
以下是我尝试过的调用代码的变体及其错误:
或者,我尝试使用方法而不是计算属性,例如
func alpha(alpha:CGFloat) -> Self {
for view in self {
view.alpha = alpha
}
return self
}
这&#34;工作&#34;但包括丑陋的演员:
我更喜欢通过MutableCollectionType
扩展程序在这些数组上使用常规属性:
loginView.subviewsOfType(UITextField.self).enabled = true
我错过了什么?
答案 0 :(得分:4)
您已完全约束UIView
,而不是UIView
的子类。你的意思是:
extension MutableCollectionType where Generator.Element: UIView { ... }
extension MutableCollectionType where Generator.Element: UIControl { ... }
请注意:
而不是==
。
在这种特殊情况下,您需要fields
成为var
,因为您要改变它:
if var fields = loginView.subviewsOfType(UITextField.self) {
fields.alpha = 0.3
fields.enabled = true
}
答案 1 :(得分:4)
有两个问题。作为Rob already said,您必须限制
UIView
/ UIControl
的子类的扩展方法。
然后编译器仍抱怨
if let fields = self.view.subviewsOfType(UITextField.self) {
fields.alpha = 0.3
fields.enabled = false
}
与
error: cannot assign to property: 'fields' is a 'let' constant
原因是设置属性被视为变异 数组(值类型),你不能改变常量。
但是,您的案例中的数组元素本身是引用类型
(班级的实例)。 setter方法只改变引用的对象,并保留
数组本身不变。因此,您可以声明setter方法
作为nonmutating
:
var alpha:CGFloat {
get { ... }
nonmutating set {
for view in self {
view.alpha = newValue
}
}
}
现在上面的代码编译和工作没有问题。