具有动态返回类型的表单输入

Posted

技术标签:

【中文标题】具有动态返回类型的表单输入【英文标题】:Form Input with dynamic return type 【发布时间】:2017-10-13 09:40:06 【问题描述】:

我想开发一个动态表单输入,它可能只是一个 UITextField 或 UIDatePicker。表单输入应使用类型(枚举)初始化,因此根据初始化的类型返回字符串或日期。也许以后我会想添加更多返回其他东西的特定类型。

使用 Swift 4 执行此操作的最佳做​​法是什么?您会将数据存储在哪里(如名字、姓氏、生日)?在控制器中?泛型类型是一种可能的解决方案吗?

欢呼

10 月 18 日编辑

感谢用户 Palle 的支持!最终的解决方案看起来像这样:

FormItem.swift

// enum with types for inputs
enum FormItemType: Int 
  case text = 0
  case date = 1


// enum with types of values
enum FormInputValue 
  case text(String)
  case date(Date)


// FormItem holds value, label and input
class FormItem: UIView 
  var value: FormInputValue?
  var label: FormLabel?
  var input: FormInput?

FormInput.swift

// Protocol to delegate the change to the controller
protocol FormInputDelegate: NSObjectProtocol 
  func inputDidChange(value: FormInputValue)


// FormInput holds the actual input
class FormInput: UIView 

  var formInput: FormInput?
  var delegate: FormInputDelegate?

  // Init FormInput with type and optional value
  convenience init(type: FormItemType, value: FormInputValue?)   
    switch type 
      case .text(let text)?:
        self.initTextInput(label: label, value: text)
        break
      case .date(let date)?:
        self.initDateInput(label: label, value: date)
        break
      case .none:
        break;
    
  

  // Init specific String input field
  fileprivate func initTextInput (label: String, value: String?) 
    formInput = FormTextInput(label: label, value: value)
    self.addSubview(formInput!)
  

  // Init specific Date input field
  fileprivate func initDateInput (label: String, value: Date?) 
    formInput = FormDateInput(label: label, value: value)
    self.addSubview(formInput!)
  

FormTextInput.swift

// Init actual input with label and optional value
convenience init(label: String, value: String?) 
  [...]

CreateViewController.swift

// Create View Controller where FormInputs 
class CreateViewController: UIViewController 

  var firstname: String = "Test 123"

  // Init view controller and add FormItem
  convenience init() 
    let fistnameFormItem = FormItem(type: .text, label: NSLocalizedString("Input.Label.Firstname", comment: ""), value: FormInputValue.text(firstname))
  

【问题讨论】:

【参考方案1】:

我会使用单独的输入而不是一个动态输入。

如果你真的想要一个通用输入,你可以使用带有关联值的枚举作为它的值:

enum FormInputResult 
    case date(Date)
    case name(firstName: String, lastName: String)

在模型-视图-控制器架构中,姓名和生日等数据应存储在数据模型中。控制器应该充当模型和视图之间的中介。

【讨论】:

计划是在视图控制器中有几个表单输入。一个表单输入包括一个标签和一个不同类型的输入。由于控制器持有模型,它负责处理来自表单输入的返回。所以我认为表单输入必须返回不同的类型。 我会在界面生成器中静态地执行此操作。但当然你可以用动态的方式来做。 我没有使用界面构建器或情节提要,所以我使用代码完成所有界面和组件。我添加了一个带有示例源代码的编辑,希望有人能告诉我我哪里出错了。 FormInputValue 不需要是泛型的,只需声明为enum FormInputValue ... 。您必须在 switch case 语句中解构值枚举以检索其关联值。 好的,所以枚举是enum FormInputValue case text(String) case date(Date) ,初始化器是convenience init(label: String, value: FormInputValue?),其中值是FormInputValue.text(model.firstname),对吗?但随后在FormButtonInputinputField.setTitle(value, for: .normal) 导致“无法转换'FormInputValue 类型的值?'到预期的参数类型 'String?'"

以上是关于具有动态返回类型的表单输入的主要内容,如果未能解决你的问题,请参考以下文章

typescript 具有表单输入的Angular Component父/子动态更新

生成具有唯一名称和 ID 的动态输入

vue通过后端返回值动态生成表单及动态表单的数据提交

vue通过后端返回值动态生成表单及动态表单的数据提交

Django从html页面访问动态表单值到视图[关闭]

如何在 devexpress 中向表单字段添加动态验证规则