将 NSCompoundPredicate 与列表一起使用

Posted

技术标签:

【中文标题】将 NSCompoundPredicate 与列表一起使用【英文标题】:Using NSCompoundPredicate with a list of lists 【发布时间】:2021-07-28 06:47:49 【问题描述】:

我有一个很大的食谱清单,每个食谱里面都有一份配料清单。我想编写一个查询,该查询将返回一个包含“鸡蛋”和“黄油”的食谱列表。 Here is a quick screenshot of the first few recipes in my CKRecord Type. 在下面的示例代码中,虽然也没有错误,但它没有返回任何结果。

理想情况下,最好包含部分搜索,例如“egg”仍会返回包含“eggs”作为成分的食谱。如果结果会优先考虑包含“鸡蛋”和“黄油”成分的食谱,然后在食谱列表的较低优先级上会有包含“鸡蛋”或“黄油”的食谱,这会更好.and,subpredicates 查询的优先级高于 .or,subpredicates 查询。

我发现的有关 NSCompoundPredicate 的其他 *** 帖子在处理正在查询的列表列表时在这里没有帮助(如在我的示例中,我在食谱列表中有一个 [成分] 列表)。

@objc func refresh(_ completion: @escaping (Error?) -> Void) 
    let subdeptPredicate1 = NSPredicate(format: "ANY ingredients == %@", "egg")
    let subdeptPredicate2 = NSPredicate(format: "ANY ingredients == %@", "butter")
    let predicate = NSCompoundPredicate(type: .and,subpredicates: [subdeptPredicate1, subdeptPredicate2])
        
    let sort = NSSortDescriptor(key: "recipe_id", ascending: false)
    let query = CKQuery(recordType: "Recipe", predicate: predicate)
    query.sortDescriptors = [sort]
    AttachToMainThread(forQuery: query, completion)
  

我能够使用这行代码成功返回成分中包含“黄油”或“鸡蛋”的食谱,但我希望优先考虑同时包含“鸡蛋”和“黄油”的食谱。

    let searchText: [String] = ["butter","egg"]
    let predicate = NSPredicate (format: "ANY ingredients IN %@",argumentArray: [searchText])

感谢您的帮助!

更新

我发现,如果我只有一个子谓词,那么每个返回的食谱都只有“鸡蛋”作为第一个成分。

let subdeptPredicate1 = NSPredicate(format: "ANY ingredients == %@", "egg")
let predicate = NSCompoundPredicate(type: .and,subpredicates: [subdeptPredicate1])

我确信这就是我同时使用“鸡蛋”和“黄油”时返回零结果的原因,因为它们永远不会同时出现在第一种成分中。

【问题讨论】:

请注意,== 比较字符串完全。你想改用CONTAINS吗? 感谢@Sweeper 提到这一点!当我像这样尝试“CONTAINS”时:let subdeptPredicate1 = NSPredicate(format: "ANY ingredients CONTAINS %@", "egg") 我收到一个错误:“libc++abi.dylib:以 CKException 类型的未捕获异常终止 *** 由于未捕获异常 'CKException' 而终止应用程序,原因:'无效谓词:任何成分都包含“鸡蛋”并且任何成分都包含“黄油”(错误域=CKErrorDomain 代码=12“ 中的修饰符无效:不支持的谓词修饰符:ANY”UserInfo=ck_isComparisonError=true, NSLocalizedDescription=我 见subquery 嘿@Willeke,你能帮我实现这个想法吗?当我尝试以下行 let predicate = NSPredicate(format:"(SUBQUERY(ingredients, $x, ANY ingredients == 'egg' && ANY ingredients == 'butter'))") 时,我收到错误:libc++abi.dylib: terminating with uncaught exception of type CKException *** Terminating app due to uncaught exception 'CKException', reason: 'Invalid predicate: SUBQUERY(residents , $x, ANY ingredients == "egg" AND ANY ingredients == "butter").@count != 0 (Error Domain=CKErrorDomain Code=12 " 对不起,我没有正确阅读这个问题,而且我过于复杂了。我认为这可能是 CloudKit 的问题。 【参考方案1】:

这是我的错误。我发现我解析 csv 文件的方式导致了问题。请注意,第一个成分是唯一在单词开头没有空格的成分。

这正是我想要的:

    let searchTextA: [String] = ["egg"," egg"]
    let subPred1 = NSPredicate (format: "ANY ingredients IN %@",argumentArray: [searchTextA])
    
    let searchTextB: [String] = ["butter"," butter"]
    let subPred2 = NSPredicate (format: "ANY ingredients IN %@",argumentArray: [searchTextB])
    
    let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [subPred1, subPred2])

【讨论】:

以上是关于将 NSCompoundPredicate 与列表一起使用的主要内容,如果未能解决你的问题,请参考以下文章

NSPredicate 与 NSCompoundPredicate?

NSCompoundPredicate 的 NSPredicate 数组

Xcode 6.1 中的 NSCompoundPredicate 错误

NSCompoundPredicate 混合 AND 和 OR

在 swift 3 中创建复杂的 NSCompoundPredicate

NSCompoundPredicate