什么是反映Obj的@property (nonatomic) NSArray <SomeProtocol>* items;的最佳方法,其中条目是UIView子类?
在下面的示例中,我希望存储一个UIKit组件数组(例如,UILabel、UIButton等),这些组件都符合协议,但是这会产生错误Protocol can only be used as a generic constraint because it has Self or associated type requirements。
有什么替代的方法来对此进行建模?
示例操场:
import UIKit
/// Protocol representing a form field model
protocol FieldRepresentable {}
/// Protocol representing a form UI control
protocol FormControllable {
associatedtype FieldRepresentable
init(model: FieldRepresentable)
var model: FieldRepresentable { get }
}
/// Example label model
class FormLabelElement: FieldRepresentable {}
/// Example label UI control
class FormLabel: UILabel, FormControllable {
required init(model: FormLabelElement) {
self.model = model
super.init(frame: CGRect.zero)
}
let model: FormLabelElement
required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
/// Example form
class Form: UIView {
// Error here
var fields: [FormControllable]?
}发布于 2016-11-21 18:25:25
Nate Cook建议
一种简单的方法是从
FormControllable中删除关联类型并使其init失效。每个符合标准的类型基本上都必须验证它是否知道如何处理传递的特定FieldRepresentable类型。我认为你会失去一些类型的安全性/表达式,但是你会获得一个非均匀数组的能力。
因此,这种方法的最终版本是:
import UIKit
/// Protocol representing a form field model that is used to instantiate a UI control
protocol FieldRepresentable: class {}
/// Protocol representing a form UI control
protocol FormControllable: class {
init?(model: FieldRepresentable)
}
/// Example label model
class FormLabelElement: FieldRepresentable {}
/// Example label UI control
class FormLabel: UILabel, FormControllable {
required init?(model: FieldRepresentable) {
guard let model = model as? FormLabelElement else { return nil }
self.model = model
super.init(frame: CGRect.zero)
}
let model: FormLabelElement
required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
/// Example form
class Form: UIView {
var fields = [FormControllable]()
}
// Create a form
let form = Form()
let labelModel = FormLabelElement()
let labelField = FormLabel(model: labelModel)!
form.fields.append(labelField)
print(form.fields)
form.fields.forEach { (field) in
if field is FormLabel {
print("We have a label field")
}
}或者,如果您的模型协议足够通用,Soroush建议
一种方法是将字段表示类型变成枚举,因为表单字段元素有一定数量的类型。 然后,您只需要一个大开关,它将枚举转换为一个表单元素。 您可以获取一个字段数据用例数组,并将它们映射到一个表单元素数组中。
https://stackoverflow.com/questions/40687922
复制相似问题