如何使用数组创建 NSPredicate 包含元素
Posted
技术标签:
【中文标题】如何使用数组创建 NSPredicate 包含元素【英文标题】:How to create NSPredicate with array contains element 【发布时间】:2019-08-26 13:16:59 【问题描述】:我只是拥有Address
实体,其属性为favourites
,类型为[String]
地址
@objc(Address)
class Address: NSManagedObject, Observer
@NSManaged var favourites: [String]
假设我有一些地址:
1: favourites: ["a", "b", "c"]
2: favourites: ["b", "c"]
3: favourites: ["a", "c"]
4: favourites: ["a"]
5: favourites: ["b"]
现在我需要在favourites
中获取所有带有a
的地址。所以结果应该是:1, 3, 4
换句话说,我需要检查数组 is equal
中的 ANY element
是否为特定字符串,然后应该返回对象。
以下不起作用:
NSPredicate(format: "favourites CONTAINS %@", "a")
xcdatamodel
中是这样定义的:
【问题讨论】:
您是在问(至少)其中一个收藏夹是否等于字符串“a”? 您是否要求将一个数组与另一个数组进行比较? 如果favourites
是一个可转换属性,则基于它的谓词将不起作用(至少不能作为获取请求的一部分)。
@MartinR 是的 ;)
【参考方案1】:
您不能在定义为带有谓词的可转换属性的数组中进行搜索。更好地定义另一个实体
@objc(Favourite)
class Favourite: NSManagedObject
@NSManaged var name: String
以及从“地址”到“收藏夹”的一对多关系。
您可以使用谓词获取所有具有任何(即:至少一个)喜爱等于字符串“a”的地址
NSPredicate(format: "ANY favourites.name == %@", "a")
或者更好的编译器检查键路径文字:
NSPredicate(format: "ANY %K == %@", #keyPath(Address.favourites.name), "a")
对于不区分大小写的比较,您可以使用
NSPredicate(format: "ANY %K ==[c] %@", #keyPath(Address.favourites.name), "a")
【讨论】:
您好;)感谢您的帮助,但它不起作用;(我为 NSFRC 创建 NSPredicate 是否重要? @BartłomiejSemańczyk:它怎么不起作用?您没有得到任何结果或错误的结果吗? 如果我分配NSPredicate(value: true)
,那么我会得到所有这些。
@BartłomiejSemańczyk:我刚刚看到您的更新:您无法搜索可转换属性。
好的,我可以换一种方式吗?有没有办法将数组保存到核心数据并能够搜索它?【参考方案2】:
根据cheatsheet,CONTAINS
用于比较字符串。例如"Hello" CONTAINS "e"
.
对于集合,你应该使用IN
:
NSPredicate(format: "%@ IN favourites", "a")
【讨论】:
【参考方案3】:如前所述,您不能在可转换属性中进行搜索。
一个额外实体的替代方法是将与唯一分隔符连接的字符串数组保存为一个字符串,并声明一个计算属性以将字符串转换为数组,反之亦然
@NSManaged var favourites: String
private let uniqueSeparator = "®¥ð"
var favs : [String]
get return favourites.components(separatedBy: uniqueSeparator)
set favourites = newValue.joined(separator: uniqueSeparator)
那么你可以简单地写
favs.contains("a")
【讨论】:
但是对于获取的结果控制器,您必须直接过滤底层字符串属性。 @MartinR 这取决于。我在获取结果控制器中使用这些计算属性(添加 KVO 合规性)。以上是关于如何使用数组创建 NSPredicate 包含元素的主要内容,如果未能解决你的问题,请参考以下文章