使用通用KeyPath创建NSPredicate<Root, Value>

问题描述 投票:0回答:1

这是我的代码的简化版本,但我希望能够从通用

NSPredicate
初始化
KeyPath<Root, Value>
,但尽管不断尝试,我还是未能成功。有人可以帮忙吗?

PS:我知道我可以更改方法以采用

key: String
并让调用者在调用站点使用
#keypath(Object.property)
,但我不想这样做,因为我想强制使用 KeyPath 来确保编译安全.

尝试1

func makeNSPredicate<Root, Value>(keyPath: KeyPath<Root,Value>, value: Value) -> NSPredicate {
    NSPredicate(format: "%K == '\(value)'", argumentArray: [keyPath])
}

运行时错误:信号 SIGABRT

尝试2

func makeNSPredicate<Root, Value>(keyPath: KeyPath<Root,Value>, value: Value) -> NSPredicate {
    NSPredicate(format: "%K == '\(value)'", keyPath)
}

编译错误:参数类型“KeyPath”不符合预期类型“CVarArg”

尝试3

func makeNSPredicate<Root, Value>(keyPath: KeyPath<Root,Value>, value: Value) -> NSPredicate {
    NSPredicate(format: "%K == '\(value)'", #keyPath(keyPath))
}

编译错误:'#keyPath'的参数引用非'@objc'属性'keyPath'

swift core-data swift-keypath
1个回答
0
投票

您可以将

Predicate
转换为
NSPredicate
。这不适用于 every
Predicate
,但假设您正在比较 Objective-C 可见的关键路径,并且它们的值也可以在 Objective-C 中表示,那么这是可行的。

func makeNSPredicate<Root: NSObject, Value: Equatable & Codable>(keyPath: KeyPath<Root,Value>, value: Value) -> NSPredicate {
    NSPredicate(Predicate<Root> { x in
        PredicateExpressions.build_Equal(
            lhs: PredicateExpressions.build_KeyPath(
                root: PredicateExpressions.build_Arg(x),
                keyPath: keyPath
            ),
            rhs: PredicateExpressions.build_Arg(value)
        )
    })!
}

虽然

Predicate
经常在 SwiftData 上下文中使用,但您不需要导入 SwiftData 来使用它。它实际上是基金会的一部分。

请注意,此处的

Value
需要为
Codable
,因此您可能必须为您要比较的某些类型实现
Codable

© www.soinside.com 2019 - 2024. All rights reserved.