我正在尝试使用Swift中的泛型来解决某些问题,但是我做错了一些我似乎无法弄清的错误。我有2个具有相同ui组件的视图,但是它们在视觉上有所不同,但是内容相同。
因此,我想抽象化填充视图的方式,以便可以重用该代码。 (我将示例简化到最低限度。)
protocol ViewConfigurator {
associatedtype View: UIView
init(view: View)
func configure()
}
protocol PersonView: UIView {
var nameLabel: UILabel { get }
}
class BigPersonView: UIView, PersonView {
var nameLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
}
class SmallPersonView: UIView, PersonView {
var nameLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
}
class PersonViewConfigurator: ViewConfigurator {
private let view: PersonView
required init(view: PersonView) {
self.view = view
}
func configure() {
view.nameLabel.text = "Swift"
}
}
但是我在操场上遇到的错误是:
操场执行失败:
错误:MyPlayground.playground:24:7:错误:类型'PersonViewConfigurator'不符合协议'ViewConfigurator' 类PersonViewConfigurator:ViewConfigurator { ^
MyPlayground.playground:4:20:注意:无法为协议“ ViewConfigurator”推断关联的类型“ View” 关联类型视图:UIView ^
MyPlayground.playground:27:14:注意:候选人无法推断'View'='PersonView',因为'PersonView'不是类类型,因此不能从'UIView'继承 必需的init(view:PersonView){
(我认为)哪个是怪异的,因为PersonView是UIView吗?
答案 0 :(得分:0)
我认为,如果您想要通用视图,可以执行以下操作:
protocol PersonView: UIView {
static var nameLabel: UILabel {get}
}
class BigPersonView: UIView, PersonView {
static var nameLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
}
class SmallPersonView: UIView, PersonView {
static var nameLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
}
class PersonViewConfigurator<T: PersonView> {
public let testView: UILabel!
init() {
testView = T.nameLabel
}
public func configure() {
testView.text = "swift"
}
}
func test() {
let person = PersonViewConfigurator<BigPersonView>()
person.configure()
print(person.testView.text)
}
test()
此外,协议遵循严格的规则,不能与继承的类型一起使用。这意味着如果您要一个UIView,则必须为其提供一个UIView,如果您要一个PersonView,则必须为其提供一个PersonView。
这让我想知道为什么还有关联的类型?
这是我描述的代码:
protocol ViewConfigurator {
init(view: PersonView)
func configure()
}
protocol PersonView: UIView {
var nameLabel: UILabel { get }
}
class BigPersonView: UIView, PersonView {
var nameLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
}
class SmallPersonView: UIView, PersonView {
var nameLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
}
class PersonViewConfigurator: ViewConfigurator {
required init(view: PersonView) {
self.view = view
}
func configure() {
view.nameLabel.text = "swift"
}
private let view: PersonView
}