核心数据:忽略对多谓词
Core Data: To-many predicate ignored
我有 Group
<-->> Member
关系。在 class Group: NSManagedObject {
我有以下属性:
@NSManaged public var members: Set<Member>
public var status: Int16 {
set {
self.willChangeValue(forKey: "status")
self.setPrimitiveValue(newValue, forKey: "status")
self.didChangeValue(forKey: "status")
self.members.removeAll()
}
get {
self.willAccessValue(forKey: "status")
var status: Int16 = 0
if let statusKey = self.primitiveValue(forKey: "status") as? Int16 {
self.didAccessValue(forKey: "status")
status = statusKey
}
return status
}
}
在 class Member: NSManagedObject
我有以下属性:
@NSManaged public var memberOf: Group?
@NSManaged public var status: Int16
要求:过滤基于:
if Groups.status = 1
AND member.status = 1
(对于每个成员)
我有以下代码:
let statusPredicate = NSPredicate(format: "status == %@", NSNumber(integerLiteral: 1))
let statusMemberPredicate = NSPredicate(format: "ANY members.status == %d", 1)
let compoundPredicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.and, subpredicates: [statusPredicate, statusMemberPredicate])
print("compoundPredicate \(compoundPredicate)")
let requestGroups: NSFetchRequest<Group> = NSFetchRequest()
requestGroups.entity = Group.entity()
requestGroups.predicate = compoundPredicate
requestGroups.returnsObjectsAsFaults = false
requestGroups.fetchBatchSize = 20
frcGroup = NSFetchedResultsController(fetchRequest: requestGroups, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
try? frcGroup?.performFetch()
if let members = frcGroup?.fetchedObjects?.first?.members {
for member in members{
print("member.status \(member.status)")
}
}
}
我得到以下日志:
compoundPredicate status == 1 AND ANY members.status == 1
member.status 0
member.status 1
member.status 0
我也试了下面的,得到了和上面一样的日志:
let statusMemberPredicate = NSPredicate(format: "members.status CONTAINS %d", 1)
看起来它正在获取所有 members
并忽略 members.status == 1
谓词。
我做错了什么?
谓词仅确定正在获取的对象是否应包含在结果中。它对相关对象没有影响。在您的情况下,如果 Group
具有 status
= 1,并且其任何相关 Member
对象具有 status
= 1,则它将包含在结果中。但其 members
属性 不受谓词影响。它将包括所有相关成员,即使它们与谓词不匹配。所以你的结果是我所期望的。
如果要过滤 members
,您应该在获取组对象后单独进行。
我有 Group
<-->> Member
关系。在 class Group: NSManagedObject {
我有以下属性:
@NSManaged public var members: Set<Member>
public var status: Int16 {
set {
self.willChangeValue(forKey: "status")
self.setPrimitiveValue(newValue, forKey: "status")
self.didChangeValue(forKey: "status")
self.members.removeAll()
}
get {
self.willAccessValue(forKey: "status")
var status: Int16 = 0
if let statusKey = self.primitiveValue(forKey: "status") as? Int16 {
self.didAccessValue(forKey: "status")
status = statusKey
}
return status
}
}
在 class Member: NSManagedObject
我有以下属性:
@NSManaged public var memberOf: Group?
@NSManaged public var status: Int16
要求:过滤基于:
if Groups.status = 1
AND member.status = 1
(对于每个成员)
我有以下代码:
let statusPredicate = NSPredicate(format: "status == %@", NSNumber(integerLiteral: 1))
let statusMemberPredicate = NSPredicate(format: "ANY members.status == %d", 1)
let compoundPredicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.and, subpredicates: [statusPredicate, statusMemberPredicate])
print("compoundPredicate \(compoundPredicate)")
let requestGroups: NSFetchRequest<Group> = NSFetchRequest()
requestGroups.entity = Group.entity()
requestGroups.predicate = compoundPredicate
requestGroups.returnsObjectsAsFaults = false
requestGroups.fetchBatchSize = 20
frcGroup = NSFetchedResultsController(fetchRequest: requestGroups, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
try? frcGroup?.performFetch()
if let members = frcGroup?.fetchedObjects?.first?.members {
for member in members{
print("member.status \(member.status)")
}
}
}
我得到以下日志:
compoundPredicate status == 1 AND ANY members.status == 1
member.status 0
member.status 1
member.status 0
我也试了下面的,得到了和上面一样的日志:
let statusMemberPredicate = NSPredicate(format: "members.status CONTAINS %d", 1)
看起来它正在获取所有 members
并忽略 members.status == 1
谓词。
我做错了什么?
谓词仅确定正在获取的对象是否应包含在结果中。它对相关对象没有影响。在您的情况下,如果 Group
具有 status
= 1,并且其任何相关 Member
对象具有 status
= 1,则它将包含在结果中。但其 members
属性 不受谓词影响。它将包括所有相关成员,即使它们与谓词不匹配。所以你的结果是我所期望的。
如果要过滤 members
,您应该在获取组对象后单独进行。