核心数据:对多谓词被忽略

Posted

技术标签:

【中文标题】核心数据:对多谓词被忽略【英文标题】:Core Data: To-many predicate ignored 【发布时间】:2020-05-18 20:15:34 【问题描述】:

我有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

要求:过滤基于: 如果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 谓词。

我做错了什么?

【问题讨论】:

【参考方案1】:

谓词仅确定正在获取的对象是否应包含在结果中。它对相关对象没有影响。在您的情况下,如果 Group 具有 status = 1,并且其任何相关的 Member 对象具有 status = 1,那么它将包含在结果中。但是它的members 属性不受谓词的影响。它将包括所有相关成员,即使它们与谓词不匹配。所以你的结果是我所期望的。

如果你想过滤members,你应该在获取Group对象之后单独进行。

【讨论】:

谢谢。 1. members 属性不是都与[Member] 相关吗? 2. 如果我使用NSFetchedResultsControllerUITableView,在获取Group 对象后如何过滤并将其附加到数据源? 我刚试过。你所描述的有效;但是,我必须手动跟踪members。这违背了使用NSFetchedResultsController 的目的。有没有更好的方法来做到这一点? 您可以将Member 设为获取的主题。那么你的谓词将是status == 1 AND group.status == 1 啊,有道理。谢谢!太糟糕了,没有更好的方法来处理多对关系。

以上是关于核心数据:对多谓词被忽略的主要内容,如果未能解决你的问题,请参考以下文章

具有多对多谓词的核心数据

核心数据关系中对象的谓词

核心数据:有序关系中第一个元素的谓词

Core Data 多对多谓词(再次)

核心数据和关系谓词

从 setEditing 更改核心数据谓词