0

给定 a KeyPath<Root, Value>,是否有一种干净的方法来测试是否Value.self是 a Set?对于 Core Data,我想指定一个接受 的 API KeyPath<Root, Value>,并且可以使用它来确定它是否是toMany关系。到目前为止,我最好的尝试是指定一个协议:

extension CollectionQueryable {

    var isToMany: Bool {
        return false
    }
}

然后,让所有KeyPaths 符合它:

extension KeyPath: CollectionQueryable { }

然后有条件地返回true有效的两种情况:NSOrderedSetSet

extension KeyPath where Value == NSOrderedSet {

    var isToMany: Bool {
        return true
    }
}

extension KeyPath where Value: Set {

    var isToMany: Bool {
        return true
    }
}

但是编译器抱怨我没有指定Set这里的泛型类型。如果我将它切换到Collection,编译器会很高兴,但这不起作用,因为它返回truewhen Valueis aString在这种情况下是非常错误的。

4

2 回答 2

1

您可以通过使用重载函数来反转泛型的注入方式。这将使您避免缺少泛型问题,并且还具有在行为上明确的好处。

func isToMany<Root, Value>(_ keyPath: KeyPath<Root, Value>) -> Bool {
    return false
}

func isToMany<Root>(_ keyPath: KeyPath<Root, NSOrderedSet>) -> Bool {
    return true
}

func isToMany<Root, Element>(_ keyPath: KeyPath<Root, Set<Element>>) -> Bool {
    return true
}
于 2020-01-03T16:25:46.743 回答
0

我最终使用了其中Optional一篇文章中的类型擦除技术来实现我想要的仅给出Type信息的内容:

protocol ToManyProtocol {
    static var elementType: Any.Type { get }
}

extension Set: ToManyProtocol {
    static var elementType: Any.Type {
        return Element.self
    }
}

现在我可以toMany通过测试类型是否为来测试是否有东西ToManyProtocol

var isToMany: Bool {
    return Value.self is ToManyProtocol.Type
}
于 2020-01-03T15:35:35.250 回答