gpt4 book ai didi

ios - 符合协议(protocol)的 UIView 子类的 Swift 数组

转载 作者:行者123 更新时间:2023-11-30 12:53:28 25 4
gpt4 key购买 nike

镜像 Obj-C 的最佳方式是什么 @property (nonatomic) NSArray <SomeProtocol>* items;项目在哪里 UIView子类?

在下面的示例中,我想存储 UIKit 的数组组件(例如 UILabelUIButton 等)都符合协议(protocol),但这会产生错误 Protocol can only be used as a generic constraint because it has Self or associated type requirements

对此建模有哪些替代方法?

Playground 示例:

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]?

}

最佳答案

内特·库克建议

One simple-ish way to approach that would be to remove the associated type from FormControllable and make its init failable. Each conforming type would basically have to validate that it knows what to do with the specific FieldRepresentable type passed. I think you'd lose a little bit of type safety/expression but would gain the ability to have a non-uniform array

所以该方法的最终版本是:

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")
}
}
<小时/>

或者,如果您的模型协议(protocol)足够通用,Soroush 建议

One idea is to make your field representable type into an enum, since theres a set number of types of form field elements

Then you just need a big switch that turns an enum into a form element

And you can take an array of field data cases and map them into an array of form elements

关于ios - 符合协议(protocol)的 UIView 子类的 Swift 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40687922/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com