泛型 – 在Swift 4中,当键路径和值的类型是通用的但是相同时,如何分配给键路径?

前端之家收集整理的这篇文章主要介绍了泛型 – 在Swift 4中,当键路径和值的类型是通用的但是相同时,如何分配给键路径?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
鉴于:

struct Foo {
    var bar: String = “”
    var baz: Int? = nil
}
let values: [Any] = [“foo”,1337]
let fooPaths: [PartialKeyPath<Foo>] = [\Foo.bar,\Foo.baz] 
let protoFoo = Foo()

如何创建迭代这些键路径和值的for循环,并在类型匹配两者且keypath是可写的时将值分配给键路径?

注意:它必须使用泛型来完成,因为Foo可以具有任何类型的属性(当然,除了类型Foo).

我尝试过这样的东西:

func setKeyOnRoot<Root,Value>(_ root: Root,value: Value,key: PartialKeyPath<Root>) -> Root {
    var root = root
    if let writableKey = key as? WritableKeyPath<Root,Value> {
        root[keyPath: writableKey] = value
    }
    return root
}

但由于在调用函数之前必须将值转换为Any,因此运行时无法看到类型Value的含义.

解决方法

此实现类似于您作为您尝试的方法示例提供的内容,我相信它会产生您正在寻找的结果:

struct WritableKeyPathApplicator<Type> {
    private let applicator: (Type,Any) -> Type
    init<ValueType>(_ keyPath: WritableKeyPath<Type,ValueType>) {
        applicator = {
            var instance = $0
            if let value = $1 as? ValueType {
                instance[keyPath: keyPath] = value
            }
            return instance
        }
    }
    func apply(value: Any,to: Type) -> Type {
        return applicator(to,value)
    }
}

struct Foo {
    var bar: String = ""
    var baz: Int? = nil
}

let values: [Any] = ["foo",1337]
let fooPaths: [WritableKeyPathApplicator<Foo>] = [WritableKeyPathApplicator(\Foo.bar),WritableKeyPathApplicator(\Foo.baz)]
let protoFoo = zip(fooPaths,values).reduce(Foo()){ return $1.0.apply(value: $1.1,to: $0) }

print(protoFoo)  // prints Foo(bar: "foo",baz: Optional(1337))

这个版本做同样的事情,但使用原始问题中指定的for循环可以用以下代码替换倒数第二行:

var protoFoo = Foo()
for (applicator,value) in zip(fooPaths,values) {
    protoFoo = applicator.apply(value: value,to: protoFoo)
}

请注意,需要某些类型擦除才能使用在同一根类型上运行但具有不同值类型的单个keyPath数组.但是,在运行时,WritableKeyPathApplicator内的闭包可以专门为每个keyPath强制转换为正确的原始值类型,并且如果它是错误的类型(如上面的示例代码中),则默默地跳过该值以设置它,否则它可能会抛出错误或向控制台等打印更多有用的信息

猜你在找的Swift相关文章