首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >符合协议的UIView子类的快速数组

符合协议的UIView子类的快速数组
EN

Stack Overflow用户
提问于 2016-11-19 00:32:45
回答 1查看 544关注 0票数 0

什么是反映Obj的@property (nonatomic) NSArray <SomeProtocol>* items;的最佳方法,其中条目是UIView子类?

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

有什么替代的方法来对此进行建模?

示例操场:

代码语言:javascript
复制
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]?

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-21 18:25:25

Nate Cook建议

一种简单的方法是从FormControllable中删除关联类型并使其init失效。每个符合标准的类型基本上都必须验证它是否知道如何处理传递的特定FieldRepresentable类型。我认为你会失去一些类型的安全性/表达式,但是你会获得一个非均匀数组的能力。

因此,这种方法的最终版本是:

代码语言:javascript
复制
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建议

一种方法是将字段表示类型变成枚举,因为表单字段元素有一定数量的类型。 然后,您只需要一个大开关,它将枚举转换为一个表单元素。 您可以获取一个字段数据用例数组,并将它们映射到一个表单元素数组中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40687922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档