swift - 如何在通用协议(protocol)上使用 if-let?

标签 swift generics protocols

我有一个具有关联类型的协议(protocol):

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

然后,我有许多类使用不同类型的输入(文本字段、 TextView 等)来实现此功能(并且也从基类派生)。

我已将此协议(protocol)扩展为适用于辞职第一响应者或设置占位符或其他任何其他类型的不同类型:

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>

最佳答案

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

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

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

    }
}

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

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
    }
}

关于swift - 如何在通用协议(protocol)上使用 if-let?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38995573/

相关文章:

Java 泛型 : Unchecked cast in generic List even though already checked with instanceof

swift - 如何使用 Swift 协议(protocol)扩展来创建可以修改私有(private)属性的共享代码?

ios - TabBarController 的第二个选项卡未实例化 -> IBOutlets 为 nil

generics - 如何使用泛型类型参数定义变量?

arrays - 初始化器避免将空数组作为参数

ios - 协议(protocol)委托(delegate)不调用函数

swift - 在协议(protocol)中使用 self in 函数

swift - Firebase 批量更新/删除

ios - 当我按下运行程序时,我的游戏会加载但无法启动

ios - 如何跟踪动画状态