ios - 使用协议对类似 UITableViewCell 进行分组以减少代码
问题描述
一些背景
假设我必须显示一个可以包含各种类型组件的表单:
- 文本域
- 文本区
- 图片
- 视频
- 落下
我已经UITableViewCell
为每一个创建了,但是因为它们都是表单组件,并且它们中的每一个都有一些共同的属性,比如一些数据(formData,userEntered data)等等,我制定了一个协议,并使所有这些单元格都符合这个协议
protocol FormComponent where Self: UITableViewCell {
var property1: String? { get set }
var property2: String? { get set }
}
并像这样使我的细胞一致
class TextFieldCell: UITableViewCell, FormComponent {
var property1: String?
var property2: String?
}
问题
现在,当我必须决定UITableViewCell
要创建哪个表单组件时,我必须创建一个 switch 语句并决定要创建哪个表单组件
// Some field that I get from some computation and this same will go inside every cell no matter the type
let field = computeFieldValue()
switch fieldType {
case textField:
let cell = tableView.dequeueReusableCell(withIdentifier: TEXT_FIELD_CELL, for: indexPath) as! TextFieldCell
cell.property1 = field.property1
cell.property2 = field.property2
return cell
case textArea:
let cell = tableView.dequeueReusableCell(withIdentifier: TEXT_AREA_CELL, for: indexPath) as! TextAreaCell
cell.property1 = field.property1
cell.property2 = field.property2
return cell
}
现在,我不想初始化单元并分配case
开关内部的属性,而是想利用协议优势将开关外部的单元初始化为一种协议类型,以便我可以分配开关外部的属性值并且不要' t 需要为每种情况下的属性分配相同的值
// Some field that I get from some computation and this same will go inside every cell no matter the type
let field = computeFieldValue()
var cell = // cell initialisation which will be of type FormComponent so that I can access the property values directly from here
cell.property1 = field.property1
cell.property2 = field.property2
switch fieldType {
case textField:
// Converting that cell to TextFieldCell with the properties defined above intact
case textArea:
// Converting that cell to TextAreaCell with the properties defined above intact
}
return cell
我认为这有点像 Upcasting,我不太确定如何实现这一点。如果有一些特定于单个 fieldType 的属性,我可以向下转换为喜欢cell as! TextFieldCell
该case
部分并分配它
而且我有很多属性和很多案例(fieldType)要处理,所以这种方法会大大减少代码
解决方案
很少有模型和类的创作。你已经实现了这些,但为了检查我添加了它们
FieldType
枚举enum FieldType { case textArea, textLabel, textField }
Field
结构模型。您可能正在使用类,并且可能有更多属性struct Field { var type : FieldType var property1 : String var property2 : String }
现在您的协议,正如您在问题中已经提到的那样
protocol FormComponent where Self: UITableViewCell { var property1: String? { get set } var property2: String? { get set } }
还有一些不同种类的细胞,问题中提到了其中一个。
class TextFieldCell: UITableViewCell, FormComponent { var property1: String? var property2: String? } class TextAreaCell: UITableViewCell, FormComponent { var property1: String? var property2: String? } class TextLabelCell: UITableViewCell, FormComponent { var property1: String? var property2: String? }
现在要使所有这些工作正常进行,您需要使用我在评论中提到的协议扩展。
extension FormComponent {
func setProperties(p1 : String, p2 : String) {
self.property1 = p1
self.property2 = p2
}
}
现在cellForRow
,要制作可重用的代码,您需要编写如下代码
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let field = arrFields[indexPath.row]
var cell : FormComponent?
switch field.type {
case .textArea:
cell = tableView.dequeueReusableCell(withIdentifier: "TextAreaCell") as! TextAreaCell
case .textLabel:
cell = tableView.dequeueReusableCell(withIdentifier: "TextLabelCell") as! TextLabelCell
case .textField:
cell = tableView.dequeueReusableCell(withIdentifier: "TextViewCell") as! TextFieldCell
}
cell!.setProperties(p1: field.property1, p2: field.property2)
return cell!
}
编辑:当您将类型转换FormComponent
为TextFieldCell
. 如果万一它不起作用,请尝试下面的开关盒内的代码
case .textField:
cell = tableView.dequeueReusableCell(withIdentifier: "TextFieldCell") as! TextFieldCell
let newObject = cell as! TextFieldCell // type cast your cell
newObject.yourProperty = "New Property" // access your specified property
而已。
注意:在cellForRow
中,单元格对象是可选的,所以请确保它不会通过你的switch-cases
else 你的应用程序将崩溃。
推荐阅读
- vue.js - vue preset.json vue 创建消息
- javascript - 如何将回调的参数分配给全局变量?
- serilog - 使用 Serilog 保存到文件或本地数据库,哪个更好或更快?
- java - 如何在 Android Studio 中显示书籍列表?
- java - “AbstractButton 类型中的方法 addActionListener(ActionListener) 不适用于参数”错误
- javascript - var debug = require('debug')('express:router:route'); TypeError: require(...) 不是函数 /
- python - Python 数据库连接:ValueError:
不是 unicode 或序列 - javascript - PHP - 从 URL 中删除参数但仍传递到另一个页面
- wia - 是否有虚拟文件>扫描 WIA 驱动程序?
- c# - 在属性名称中使用 $ 反序列化 JSON