Swift类型擦除-对于这种情况?

Swift类型擦除-对于这种情况?,swift,generics,type-erasure,Swift,Generics,Type Erasure,我有实现TypeConverter的需求,后来将其用作变量类型。受ObjectMapper的启发,我定义了以下协议: protocol TypeConverter { associatedtype A associatedtype B func transformFrom(fromType: A?) -> B? func transformTo(toType: B?) -> A? } 具体实施是: class IntToStringTypeCon

我有实现TypeConverter的需求,后来将其用作变量类型。受ObjectMapper的启发,我定义了以下协议:

protocol TypeConverter {
    associatedtype A
    associatedtype B

    func transformFrom(fromType: A?) -> B?

    func transformTo(toType: B?) -> A?
}
具体实施是:

class IntToStringTypeConverter: TypeConverter {

    typealias A = Int
    typealias B = String

    func transformFrom(fromType: Int?) -> String? {
        guard let fromType = fromType else { return nil }
        return String(fromType)
    }

    func transformTo(toType: String?) -> Int? {
        guard let toType = toType else { return nil }
        return Int(toType)
    }
}
因为ProtocolTypeConverter有associatedtype,所以我不能将它声明为变量,例如:var converter:TypeConverter,但我需要这样的特性。这种情况的解决办法是使用类型擦除。按照这个链接应该是可能的,但我不知道怎么做

这是我的尝试,但它不正确:)。。。这样能解决吗?或者我应该用这个:

class AnyTypeConverter:TypeConverter{
类型别名A=Y
类型别名B=Z
私人出租从:(Z?->Y?
私人出租人:(Y?->Z?
init(iFormTypeConverter:W),其中W.A==Y,W.B==Z{
self.\u transformFrom=iFormTypeConverter.transformFrom
self.\u transformTo=iFormTypeConverter.transformTo
}
func transformFrom(型号:Y?->Z{
返回transformFrom(modelType:modelType)
}
func transformTo(iFormType:Z?->Y{
返回transformTo(iFormType:iFormType)
}
}

对于具有关联类型的协议来说,这并不是一个很好的用途。PAT是非常复杂的工具,在这种情况下根本没有理由使用它。您甚至不需要类型擦除器,只需要一个结构:

struct TypeConverter<Model, Form> {
    let transformFrom: (Model) -> Form?
    let transformTo: (Form) -> Model?
}

let stringToInt = TypeConverter(transformFrom:String.init,
                                transformTo:Int.init)

stringToInt.transformFrom(123)
stringToInt.transformTo("x")
struct-TypeConverter{
让我们从:(模型)->形式?
让我们转换到:(表单)->模型?
}
设stringToInt=TypeConverter(transformFrom:String.init,
transformTo:Int.init)
stringToInt.transformFrom(123)
stringToInt.transformTo(“x”)

当然,如果愿意的话,您可以使它符合
TypeConverter
(我可以更新以添加它),但我建议完全删除协议,只使用structs。这与格式化程序的工作原理非常接近。

在实现了两个单元格后,我发现我可以稍微简化这件事,并且只使用一种关联类型:)。单元格中使用的类型实际上是由UI组件定义的-如果有UITextField,则类型将是String,如果实现自定义stepper,则类型将是Int(例如)。如果我想使我的单元通用,那么它应该可以与任何类型一起工作,我可以为它编写模型和(预定义的)单元类型之间的转换器

protocol FormTypeConverter {

    associatedtype FormType

    func fromModelToForm(_ value: Any?) -> FormType?

    func fromFormToModel(_ value: FormType?) -> Any?
}
有了它,我可以使用如下简单的类型擦除(第一篇文章链接中的源代码)

struct AnyFormTypeConverter:FormTypeConverter{
//标记:-变量
从模特到说唱歌手的私人出租:(有吗?->T?
私人出租fromFormToModelWrapper:(T?->任何?
init(uFormTypeConverter:Y),其中Y.FormType==T{
self.fromModelToFormRapper=formTypeConverter.fromModelToForm
self.fromFormToModelWrapper=formTypeConverter.fromFormToModel
}
func fromModelToForm(u值:Any?)->T{
从ModelToFormRapper返回(值)
}
func fromFormToModel(u值:T?)->Any{
从FormToModel返回(值)
}
}

这个案例的实现非常适合。已经很快实现了两个完全不同的表单:)

用例是什么?FWIW我更喜欢使用单独的
StringConvertable
IntConvertable
协议,以及所需的类型和扩展。还有,为什么需要
TypeConverter
对象。您应该能够声明
var converter:IntToStringConverter
@gadu谢谢您的回复。请看下面的评论…我知道格式化程序是如何工作的-你不会相信,但我开始的方式与你非常相似,但不知何故它不符合我的要求。我知道格式化程序是如何工作的-你不会相信,但我开始的方式与你非常相似,但不知何故它不符合我的要求。我正在处理FormRowDescription对象,它可能有转换器来映射DataModel和CellType之间的数据类型,所以它可能是String/Int、Float/Int-anything:)。所以我需要把它变成通用的。当然,RowDescription的对象应该适用于所有情况。这就是为什么我认为它对我来说非常重要,可以选择将它声明为var转换器:ConverterType。。。如果类型擦除不会消失,它仍然是将转换器声明为Any,Any…协议AnyConverter{//非常丑陋的解决方案func fromModel(值:Any?->Any?func toModel(值:Any?->Any?}类IntoStringAnyConverter:AnyConverter{func fromModel(值:Any?->Any?)的一个选项?{guard let value=value as?Int else{return nil}return String(value)}func toModel(value:Any?->Any?{guard let value=value as?String else{return nil}return Int(value)}}类测试{var anyConverter:anyConverter init(anyConverter:anyConverter){self.anyConverter=anyConverter}}let converter=IntoStringAnyConverter()let test=test(anyConverter:converter)上面的例子适合我的需要,但它非常难看。这就是为什么我试图用更奇特的方法来解决它。当然,如果可能的话
protocol FormTypeConverter {

    associatedtype FormType

    func fromModelToForm(_ value: Any?) -> FormType?

    func fromFormToModel(_ value: FormType?) -> Any?
}
struct AnyFormTypeConverter<T>: FormTypeConverter {

    // MARK: - Variables

    private let fromModelToFormWrapper: (Any?) -> T?
    private let fromFormToModelWrapper: (T?) -> Any?

    init<Y: FormTypeConverter>(_ formTypeConverter: Y) where Y.FormType == T {
        self.fromModelToFormWrapper = formTypeConverter.fromModelToForm
        self.fromFormToModelWrapper = formTypeConverter.fromFormToModel
    }

    func fromModelToForm(_ value: Any?) -> T? {
        return fromModelToFormWrapper(value)
    }

    func fromFormToModel(_ value: T?) -> Any? {
        return fromFormToModel(value)
    }
}