ios - NSFetchedResultsController或谓词在iOS6上针对某些项目返回重复项

标签 ios sql core-data predicate nsfetchedresultscontroller

我正在使用NSFetchedResultsController将不同电子邮件帐户的消息加载到表视图和集合视图中。在iOS7上一切正常,在iOS6 EXCEPT上任何地方一切正常,当我使用组合OR谓词时。

现在我知道,如果NSFetchedResultsController匹配多个谓词,它将返回两次相同的项。我的问题是消息实体仅匹配这些谓词之一,却被返回与谓词相同的次数。

因此,出于某种原因,NSFetchedResultsController表示这些消息通过所有谓词,但仅在iOS6上通过。这样做是针对来自特定电子邮件帐户的每条消息,而不是针对来自其他帐户的消息。

如果我将OR谓词调整为不使用ObjectID,则会返回唯一的结果。但是,随着值的调整,我的用户界面将不再正确更新

在我的一生中,我似乎无法弄清楚这些实体到底如何传递其他电子邮件帐户和文件夹的谓词。

我的谓词构造导致重复,如下所示。帐户->消息是oneToMany关系,文件夹<->消息是manyToMany。

                NSMutableArray *predicates = [NSMutableArray array];
                for (CRMFolder *folder in comboFolder.folders) {
                    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isMarkedForDelete != YES AND isTopReferenceMessage = YES AND folders contains %@ AND account = %@", folder, folder.account];
                    [predicates addObject:predicate];
                }
                fetchRequest.predicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];


因此,如果像这样将其更改为objectID,则会得到独特的结果:

                NSMutableArray *predicates = [NSMutableArray array];
                for (CRMFolder *folder in comboFolder.folders) {
                    NSArray *objectIDs = [folder.messages valueForKey:@"objectID"];
                    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isMarkedForDelete != YES AND isTopReferenceMessage = YES AND self in %@", objectIDs];
                    [predicates addObject:predicate];
                }
                fetchRequest.predicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];


但是,如果我将两者结合起来,我仍然会重复。

                NSMutableArray *predicates = [NSMutableArray array];
                for (CRMFolder *folder in comboFolder.folders) {
                    NSArray *objectIDs = [folder.messages valueForKey:@"objectID"];
                    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isMarkedForDelete != YES AND isTopReferenceMessage = YES AND folders contains %@ AND account = %@ AND self in %@", folder, folder.account, objectIDs];
                    [predicates addObject:predicate];
                }
                fetchRequest.predicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];


任何想法

1)为什么这些实体传递不应该通过的谓词?

2)为什么这只会在iOS6上发生?

3)解决方法是什么?

我知道我可以使用returnDistinctResults,但是这需要将所有内容都转换为字典,目前这不是一个选择。

编辑

我刚刚进行了测试,如果我排除了创建问题的帐户,则结果是正常的。同样,我只是排除了所有其他帐户,没有重复的帐户。因此,只有当这些谓词全部结合时,才会发生这种情况。我真的怀疑获取的结果控制器中存在一些错误。

编辑2

这是产生多个重复的提取的原始CoreData日志。请注意,有3条消息重复9次以得到27个结果。

CoreData:批注:sql连接获取时间:0.0528s
CoreData:sql:从Z_3BLINDCARBONCOPYMESSAGES中选择t0.Z_PK,t1.Z_14BLINDCARBONCOPYMESSAGES t1在t0上加入ZCRMADDRESS t0.Z_PK = t1.Z_3BLINDCARBONCOPIES在其t1.Z_14 276,276 276,276 276,276,276 276,276,276 276,276,276 286、286、286、286、286、286、286、286、286、286、624、624、624、624、624、624、624、624、624)按t1.Z_14BLINDCARBONCOPYMESSAGES ASC排序
CoreData:批注:sql执行时间:0.0004s
CoreData:批注:从联接表中预取数据库中的多对多关系“ blindCarbonCopies”。得到了0行
CoreData:sql:从z_14REFERENCEMESSAGEs t1 SELECT t0.Z_PK,t1.REFLEXIVE t1上t0.Z_PK = t1.Z_14REFERENCEMESSAGES在t1.REFLEXIVE IN(276、276、276、276、276、276、276、276、276、276、276、276、276、276、276、276、276、276、276、276 286、286、286、286、286、286、286、286、286、624、624、624、624、624、624、624、624、624)按t1排序。
CoreData:批注:sql执行时间:0.0525s
CoreData:批注:从联接表中预取数据库中的多对多关系“ referenceMessages”。得到了0行
CoreData:sql:从Z_3CARCOPONMESSAGES中选择t0.Z_PK,t1.Z_14CARBONCOPYMESSAGES t1在t0上加入ZCRMADDRESS t0.Z_PK = t1.Z_3 CARBONCOPIES在t1.Z_14CARBONCOPYMESSAGE IN(276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276 286、286、286、286、286、286、286、286、286、286、624、624、624、624、624、624、624、624、624)按t1.Z_14CARBONCOPYMESSAGES ASC排序
CoreData:批注:sql执行时间:0.0270s
CoreData:批注:从联接表中预取数据库中的多对多关系“ carbonCopies”。得到了0行
CoreData:sql:从Z_3SENDERMESSAGES t1中选择t0.Z_PK,t1.Z_14SENDERMESSAGES在t0.Z_PK = t1.Z_3SENDERS中加入t0.Z_PKSENDERS t0.Z_14SENDERMESSAGES IN(276,276,276,276,276,276,276,276 286、286、286、286、286、286、286、286、286、286、624、624、624、624、624、624、624、624、624)按t1.Z_14SENDERMESSAGES ASC排序
CoreData:批注:sql执行时间:0.0007s
CoreData:批注:从连接表中预取数据库中的多对多关系“发件人”。有6行
CoreData:sql:SELECT 0,t0.Z_PK,t0.Z_OPT,t0.ZEMAIL,t0.ZLABEL,t0.ZNAME,t0.ZPRIMARYADDRESS,t0.ZPROFILEPHOTO,t0.ZPROFILEPHOTOLASTCACHEDATE,t0.ZPROFILEPHOTOSOURCE,t0.ZCONATE从ZCRMADDRESS t0到t0.Z_PK IN(?,?,?)
CoreData:批注:sql连接获取时间:0.0004s
CoreData:批注:总提取执行时间:3行0.0007s。
CoreData:批注:使用键“发件人”进行预取。有3行。
CoreData:sql:SELECT 0,t0.Z_PK,t0.Z_OPT,t0.ZCONTENTID,t0.ZCONTENTTYPE,t0.ZDATA,t0.ZDATE,t0.ZEXCHANGEID,t0.ZFILEEXTENSION,t0.ZISLOCAL,t0.ZISTEMPORARY,t0.ZORIGINAL ,t0.ZSIZEINBYTES,t0.ZTHUMBNAIL,t0.ZMESSAGE,t0.Zuser来自ZCRMATTACHMENT t0,其中t0.ZMESSAGE在(?,?,?,?,?,?,?,?,?,?,?,?,? ,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)按t0排序。
CoreData:批注:sql连接获取时间:0.0005s
CoreData:批注:总读取执行时间:0行为0.0007s。
CoreData:批注:使用键“附件”进行预取。得到了0行。
CoreData:sql:从Z_3REPLYTOMESSAGES中选择SELECT t0.Z_PK,t1.Z_14 286、286、286、286、286、286、286、286、286、286、624、624、624、624、624、624、624、624、624)按t1.Z_14REPLYTOMESSAGES ASC排序
CoreData:批注:sql执行时间:0.0006s
CoreData:批注:从连接表中预取数据库中的多对多关系“ replyTos”。有6行
CoreData:sql:SELECT 0,t0.Z_PK,t0.Z_OPT,t0.ZEMAIL,t0.ZLABEL,t0.ZNAME,t0.ZPRIMARYADDRESS,t0.ZPROFILEPHOTO,t0.ZPROFILEPHOTOLASTCACHEDATE,t0.ZPROFILEPHOTOSOURCE,t0.ZCONATE从ZCRMADDRESS t0到t0.Z_PK IN(?,?,?)
CoreData:批注:sql连接获取时间:0.0004s
CoreData:批注:总提取执行时间:3行0.0006s。
CoreData:批注:使用键“ replyTos”进行预取。有3行。
CoreData:SQL:SELECT t0.Z_PK,t1.Z_14RECIPIENTMESSAGES FROM Z_3RECIPIENTMESSAGES T1 JOIN ZCRMADDRESS T0 ON t0.Z_PK = t1.Z_3RECIPIENTS WHERE t1.Z_14RECIPIENTMESSAGES IN(276,276,276,276,276,276,276,276,276, 286、286、286、286、286、286、286、286、286、286、624、624、624、624、624、624、624、624、624)按t1.Z_14RECIPIENTMESSAGES ASC排序
CoreData:批注:sql执行时间:0.0006s
CoreData:批注:从连接表中预取数据库中的多对多关系“收件人”。有6行
CoreData:sql:SELECT 0,t0.Z_PK,t0.Z_OPT,t0.ZEMAIL,t0.ZLABEL,t0.ZNAME,t0.ZPRIMARYADDRESS,t0.ZPROFILEPHOTO,t0.ZPROFILEPHOTOLASTCACHEDATE,t0.ZPROFILEPHOTOSOURCE,t0.ZCONATE从ZCRMADDRESS t0到t0.Z_PK IN(?)
CoreData:批注:sql连接获取时间:0.0004s
CoreData:批注:总提取执行时间:1行0.0007s。
CoreData:批注:使用关键“收件人”进行预取。有1行。
CoreData:sql:SELECT 0,t0.Z_PK,t0.Z_OPT,t0.ZENCRYPTEDBODY,t0.ZENCRYPTEDHTMLBODY,t0.ZENCRYPTEDPLAINTEXTBODY,t0.ZENCRYPTEDSUBJECT,t0.ZCRESSAGEBODY来自ZCRESSESSAGEBODY t0?在T0吗?? ,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
CoreData:批注:sql连接获取时间:0.0011s
CoreData:批注:总提取执行时间:3行0.0015s。
CoreData:批注:使用键“ messageBody”进行预取。有3行。
CoreData:批注:总提取执行时间:27行为0.1482s。

最佳答案

正如Dan Shelly指出的那样,在谓词中错误地使用了CONTAINS。我相信,正如他解释的那样,这仅是为了在另一个字符串中找到一个子字符串。请参见predicate documentation。但是,出于您的目的,您可以改用子查询。

因此,我将继续解决问题。您可以将子谓词更改为以下内容:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isMarkedForDelete != YES AND isTopReferenceMessage = YES AND SUBQUERY(folders, $folder, $folder = %@).@count != 0 AND account = %@", folder, folder.account];


如Martin R.所述,获取请求不应两次返回相同的元素。我不知道为什么这样做,如果确实如此,除非是由于使用了无效谓词。

另外,请注意,由于获取请求不应返回重复项,因此returnsDistinctResults的用法与听起来有些不同。您可以找到示例here

关于ios - NSFetchedResultsController或谓词在iOS6上针对某些项目返回重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21997456/

相关文章:

iphone - Float on core-data 的问题

ios - 将 NSUrl 转换为 PHAsset iOS 8

ios - 如何更新 iPhone 应用程序中的数据

iphone - iOS 自定义 TabBar 高度

php - SELECT id 其中来自多列的最小值或最大值

ios - 使用 nil 必需属性保存上下文时,Core Data 自定义访问器崩溃

cocoa - Core Data MagicalRecord 在线程中合并 MOC

ios - iOS未授权的网络连接(401)

mysql - 将 SumIfs Excel 函数转换为 MySQL

php - 通过sql和codeigniter检索数据