需要有关如何对动态构建的tableviews执行验证的建议

时间:2017-05-03 18:10:08

标签: ios uitableview

我正在开发一个应用程序,其中包含13个可以填写并发送到Web服务的表单。所有这些表单都包含多个字段,但有多个字段包含在多个表单中。

当然,我可以采取简单创建13个视图控制器的路线。表单在不久的将来不会改变,所以静态单元格可以做到这一点,但在代码和故事板中创建13个视图控制器看起来并不优雅。

所以我决定使用各种动态原型单元创建一个视图控制器,然后在需要时可以使用不同类型的表单。

我创建了一个简单的模型,并使用选定的FormType查看该表单中需要哪些字段(tableview单元格)。

struct Form {
let type: FormType
let identifier: String
let cellTypes: [CellType]
let requiredFieldsIndexes: [Int]

}

enum FormType: String {
case permissionEndPoint = "FAP-11"
case other2 = "2"
// etc...

}

然后我在代码中创建了13个表单:

Form(type: .permissionEndPoint, identifier: "SAP.01", cellTypes: Array([.kilometerConstraints,.additionalInformation,.permissionNumber]),requiredFieldsIndexes: [0])

并使用tableview委托方法显示正确的字段.func tableView(_ tableView:UITableView,numberOfRowsInSection section:Int) - > Int {         return displayedForm.cellTypes.count     }

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let identifier = displayedForm.cellTypes[indexPath.row]

    switch identifier {
    case .trafficControlCenter:
        return tableView.dequeueReusableCell(withIdentifier: identifier.rawValue, for: indexPath)
    case .trainInformation:
        return tableView.dequeueReusableCell(withIdentifier: identifier.rawValue, for: indexPath)
    case .permissionAtLocation:
        return tableView.dequeueReusableCell(withIdentifier: identifier.rawValue, for: indexPath)
    case .notUsed:
        let cell = tableView.dequeueReusableCell(withIdentifier: identifier.rawValue, for: indexPath) as! NotUsedTableViewCell
        return cell
    case .additionalInformation:
        let cell = tableView.dequeueReusableCell(withIdentifier: identifier.rawValue, for: indexPath) as! AdditionalInformationCell
        cell.additionalInfoTextView.delegate = self
        return cell
    default:
        return tableView.dequeueReusableCell(withIdentifier: identifier.rawValue, for: indexPath)
    }
}`

这很有效,但是我需要检查是否确定某些字段是否已填写,收集数据,并以特定格式将数据发送到网络。由于我不确切知道显示哪些字段,我应该如何访问不同的字段?也许我可以创建一个对所有相关IBOutlets(textfields,textviews和datepickers)的引用来检查这些?

我的常规设置是否正常或是否有更简单的方法来模拟此问题?

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

您的解决方案中有不同的移动部件,重要的是将关注点分隔在不同的类之间。

遵循MVC模式,我就是这样做的:

  • 对于每个单元格,创建一个UITableViewCell的子类,其中包含单元格中所有必要的控件出口(文本字段,滑块,开关等)。
  • 单元格也应该是这些控件的委托(例如,UITextFieldDelegate)或控件操作的接收者,例如UISwitch,以检测用户何时更改表单中的值。
  • 当值更改时,单元格会将此类更改传递给自己的自定义委托。您可以通过自定义协议为您的单元子类实现此功能。代表必须存储单元格数据。这是因为在表视图中,当单元格离开屏幕时,它可能会被重用而不能保持其状态。因此,单元格需要将其传达给外部对象,否则您将丢失用户输入。
  • 表视图中所有单元格的委托应该是数据源(可能是您的视图控制器或单独的对象)。数据源可以将自己设置为上面显示的tableView(_:cellForRowAt:)方法中每个单元格的委托。
  • 每当单元格报告其数据发生更改时,数据源都会将此类数据存储在数组中。您可以向表视图询问单元格的索引路径,以便了解数组中哪个索引存储此类数据
  • 每次调用tableView(_:cellForRowAt:)方法使单元格出列时,都会使用存储在数据源中的数据重新填充单元格。正如我所说,单元格可以重复使用,因此你可以获得一个包含其他数据的重用单元格,或者一个新出列的空单元格。这就是您需要将数据传回给它的原因。如果你不这样做,用户将在表格中看到奇怪的值,如果他上下滚动。
  • 当您需要提交整个表单的数据时,您会发现它已存储在数据源中的数组中。