简体   繁体   English

Swift扩展到MutableCollectionType不使用泛型类型数组

[英]Swift extension to MutableCollectionType not working with array of generic types

I have an extension on UIView that returns an array of sub-views based on meta type. 我在UIView上有一个扩展,它根据元类型返回一个子视图数组。 This way I can query the view hierarchy for example for all UITextFields, etc. 这样我可以查询视图层次结构,例如所有UITextFields等。

extension UIView {
    func subviewsOfType<T:UIView>(_:T.Type) -> [T]? {
        ...
    }
}

This can be called like so: 这可以像这样调用:

let fields = loginView.subviewsOfType(UITextField.self)

Now, I would like to act on that array [UITextField] with an interface that matches the generic passed in, in other words whatever is available on UITextField, example: 现在,我想在该数组[UITextField]使用与传入的泛型相匹配的接口,换句话说,UITextField上可用的任何内容,例如:

fields.alpha = 0.3 // via UIView
fields.enabled = false // via UIControl

I have created extensions on MutableCollectionType to provide these overrides: 我在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
            }
        }
    }
}

However, when I try to use these extensions they do not work as expected. 但是,当我尝试使用这些扩展时,它们无法按预期工作。 :( :(

Here are the variations of calling code I have tried and their errors: 以下是我尝试过的调用代码的变体及其错误:

对成员alpha的模糊引用

无法分配给属性字段是让常量

无法分配给类型的不可变表达式

启用了对成员的模糊引用

Alternatively, I tried using methods instead of computed properties, eg 或者,我尝试使用方法而不是计算属性,例如

func alpha(alpha:CGFloat) -> Self {
    for view in self {
        view.alpha = alpha
    }
    return self
}

This "works" but includes ugly casting: 这“有效”,但包括难看的铸造:

使用setter

I would prefer to use regular properties on those arrays via the MutableCollectionType extensions: 我更喜欢通过MutableCollectionType扩展在这些数组上使用常规属性:

loginView.subviewsOfType(UITextField.self).enabled = true

What am I missing?? 我错过了什么?

You've constrained to exactly UIView , not subclasses of UIView . 你已经完全限制了UIView ,而不是UIView子类。 You meant this: 你的意思是:

extension MutableCollectionType where Generator.Element: UIView { ... }
extension MutableCollectionType where Generator.Element: UIControl { ... }

Note the : rather than == . 注意:而不是==

And in this particular case, you'll need fields to be a var since you mutate it: 在这种特殊情况下,您需要将fields变为var因为您将其变异:

if var fields = loginView.subviewsOfType(UITextField.self) {
    fields.alpha = 0.3
    fields.enabled = true
}

There are two problems. 有两个问题。 As Rob already said , you have to restrict the extension methods to subclasses of UIView / UIControl . 正如Rob已经说过的 ,你必须将扩展方法限制为UIView / UIControl 子类

But then the compiler still complains on 但随后编译器仍抱怨

if let fields = self.view.subviewsOfType(UITextField.self) {
    fields.alpha = 0.3
    fields.enabled = false
}

with

error: cannot assign to property: 'fields' is a 'let' constant

The reason is that setting a property is considered a mutation of the array (which is a value type ), and you cannot mutate constants. 原因是设置属性被认为是数组的变异 (这是一种值类型 ),并且您不能改变常量。

However, the array elements itself in your case are reference types (instances of a class). 但是,在您的情况下,数组元素本身是引用类型 (类的实例)。 The setter methods mutate only the referenced objects, and leave the array itself unchanged. setter方法只改变引用的对象,并保持数组本身不变。 Therefore you can declare the setter method as nonmutating : 因此,您可以将setter方法声明nonmutating

var alpha:CGFloat {
    get { ... }
    nonmutating set {
        for view in self {
            view.alpha = newValue
        }
    }
}

And now the above code compiles and works without problems. 现在上面的代码编译和工作没有问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM