【问题标题】:How to if-let on a generic protocol?如何在通用协议上进行 if-let?
【发布时间】:2016-12-24 01:10:30
【问题描述】:

我有一个关联类型的协议:

protocol FormInputType {
  associatedtype Input
  var field: Input! { get set }
}  

然后,我有许多类使用不同类型的输入(文本字段、文本视图等)实现这一点(并且也派生自基类)。

我已经为那些不同的类型扩展了这个协议,以便让第一响应者辞职,或者设置占位符,或者其他任何东西:

extension FormInputType where Self.Input == UIResponder
extension FormInputType where Self.Input == UITextView

然后我有一个包含这些数组的类。示例:

let array: [FormField] = [InputTextView(), InputTextField(), InputTextField()]

如何在我的其他班级中调用 FormInputType 扩展上的方法?看来我不能if let 通用约束。如何遍历数组以查看它们是否与约束匹配?

更多信息:

class FormField
{
}

class InputTextView: FormField, FormInputType {
  var field: UITextView!
}
class InputTextField: FormField, FormInputType {
  var field: UITextField!
}

然后我怎样才能执行类似 for 循环的操作,检查特定字段是否符合 FormInputType where Input == UIResponder(例如),类似于您如何创建函数并执行 <T: FormInputType where T.Input == UIResponder>

【问题讨论】:

  • 什么是InputTextView?请显示真实数组。它是如何定义的以及如何填充的。最后你在你的 2 个扩展里面写了什么?
  • @appzYourLife 复制/粘贴所有内容的代码太多,但这里是一般样式和所涉及的玩家。
  • 你可能需要一些type erasure这里...

标签: swift generics protocols


【解决方案1】:

您必须将其强制转换为实现FormInputType 协议的特定类。这是 Swift 采用的静态类型系统的一个缺点。

如果你写这个,Swift 不知道FormInputType.Input 是什么类型:

for item in array {
    if let item = item as? FormInputType { // Compiler error. What type is `field`?

    }
}

相反,将其转换为符合协议的特定类:

for item in array {
    switch item {
    case let item as InputTextView:
        // Now we are sure that `field` is UITextView
    case let item as InputTextField:
        // Now we are sure that `field` is UITextField
    default:
        // Unknown type
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多