【问题标题】:CoreStore sectioned list monitor how to specify .where clause in runtimeCoreStore 分段列表监控如何在运行时指定 .where 子句
【发布时间】:2019-08-30 18:44:26
【问题描述】:

我的 init 方法中有这段代码:

self.monitor = CoreStore.monitorSectionedList(
        From<ListEntityType>()
            .sectionBy(#keyPath(ListEntityType.muscle.name)) { (sectionName) -> String? in
                return "\(String(describing: sectionName)) years old"
            }
            .orderBy(.ascending(#keyPath(ListEntityType.muscle.name)), .ascending(\.name))
    )

我想以某种方式在运行时向此监视器添加.where 条件。

ListEntityType 是名为Exercise 的实体的类型别名。所以每个Exercise 都包含一对一的关系Muscle (exercise.muscle)。

每个实体都有唯一的标识符属性。

我有一组肌肉标识符,我想将其用作过滤器以显示分段列表中的对象。

如何循环通过此标识符将 then to .where 子句添加到CoreStore.monitorSectionedList

我可能期待这样的事情,但不是 100% 肯定只是假设:

让谓词 = NSPredicate(格式: "%K = $ARGUMENT")

    var predicates = [NSPredicate]()

    if let muscles : [MuscleGroupEntity] = workout?.muscles.toArray() {
        for muscle in muscles
        {
            let myNewPredicate = predicate.withSubstitutionVariables(["ARGUMENT" : muscle.id])
            predicates.append(myNewPredicate)
        }
    }

    self.monitor = CoreStore.monitorSectionedList(
        From<ListEntityType>()
            .sectionBy(#keyPath(ListEntityType.muscle.name)) { (sectionName) -> String? in
                return "\(String(describing: sectionName)) years old"
            }
            .where(format:"%K = %@", argumentArray: predicates)
            .orderBy(.ascending(#keyPath(ListEntityType.muscle.name)), .ascending(\.name))
    )

此代码因错误而崩溃:

-[NSComparisonPredicate rangeOfString:]: unrecognized selector sent to

我猜这是我找到的谓词here 中的东西,但不确定在我的情况下如何正确使用它

为 MartinM cmets 编辑:

我有一个带有 Muscle 属性的 ExerciseEntity。

如果我想只使用一块肌肉进行所有锻炼,这很简单:

.where(format:"%K = %@", #keyPath(ExerciseEntity.muscle.id), "id_12345")

但我想指定更多肌肉并在运行时定义它们。不知何故,我需要了解格式是什么,参数是什么以及如何传递标识符数组而不是一个 "id_12345"

【问题讨论】:

  • 如果我错了,请纠正我,但我猜你想要一个 (id IN muscleIds) 谓词?获取所有 ListEntityTypes 其中 ListEntityType.muscle.id 包含在锻炼.muscles.ids 中?
  • @MartinM 我在上面的问题中添加了一个编辑部分。感谢您的帮助!)

标签: ios swift core-data nspredicate corestore


【解决方案1】:

如果您想获取所有的“运动实体”,其中他们的肌肉.id 包含在肌肉ID 列表中,您只需使用:

let muscleIds = workout?.muscles.compactMap({ $0.id }) ?? []
From....
   .where(Where<ExerciseEntity>(#keyPath(ExerciseEntity.muscle.id), isMemberOf: muscleIds))

这相当于一个谓词,格式为:%K IN %@,ExerciseEntity.muscle.id,muscleIds

这也适用于否定 -> NOT(%K IN %@),就像您可以在 CoreStore 中使用 !Where 一样。

复合谓词需要指定它们的链接方式。 CoreStore 一次支持 2 个谓词的简写,使用逻辑运算符,例如:

Where<ExerciseEntity>(yourWhereClause) && Where<ExerciseEntity(otherWhereClause)

这相当于像这样使用 NSCompoundPredicate:

NSCompoundPredicate(type: .and, subpredicates: [left.predicate, right.predicate])

如果您需要更复杂的连词,您也可以将该复合谓词作为参数直接传递给 where 子句。然后,您还可以将该复合谓词存储在某处,并附加另一个符合您需要的复合谓词。

【讨论】:

  • 感谢帮助,我会试试的。如果我需要实现搜索,我该如何结合几个 .where 使用你在这个one 中建议的这个你已经回答了。
  • 应该是这样的link:.where(Where&lt;ListEntityType&gt;("%K CONTAINS[cd] %@", #keyPath(ListEntityType.name), searchText) &amp;&amp; Where&lt; ListEntityType&gt;(#keyPath(ExerciseEntity.muscle.id), isMemberOf: muscleIds))
  • 如果您知道如何构建谓词数组以传递给 where 函数。它会很棒,所以它对我很有帮助和灵活性,因为我可以组合任何谓词并将其作为过滤器。一如既往的感谢!
  • 您不能简单地传入谓词列表。您需要指定如何使用 AND、OR 来创建复合谓词。这取决于你的逻辑你需要什么。想想如何在运行时构建查询链以及可显示数据背后的逻辑是什么。让事情尽可能简单,
  • 是的,您的代码运行良好,但如果您能提供复合谓词的示例,那就太好了!
【解决方案2】:

我看起来 coreStore 是一个很酷的 core-data 包装器,并且 'where' 方法在幕后创建了一个 NSPredicate。问题是您将谓词数组传递给需要字符串的方法。

首先将您的谓词数组转换为单个谓词。使用NSCompoundPredicateandPredicateWithSubpredicates(见https://developer.apple.com/documentation/foundation/nscompoundpredicate/1407855-init)。

接下来,不要使用格式通过字符串传递它,而是直接将其传递给 where() 子句,而不使用单词格式。我相信 CoreStore 直接接受 NSPredicates 而无需从格式创建它们。

我认为这会奏效:

 .where(NSCompoundPredicate.init(andPredicateWithSubpredicates: predicates))

【讨论】:

  • 感谢 Jon,是的,我看到 NSPredicate 上有一些设置,但有时我很难理解如何使用函数的语法。我知道我需要更多地了解泛型。目前我尝试了你的代码,但编译器告诉我一个错误Cannot invoke 'where' with an argument list of type '(NSCompoundPredicate)',因为你可以看到很少有参数 .where 需要formatargs
  • 好像核心存储的where支持&&操作符见github.com/JohnEstropia/CoreStore/blob/…。也许你可以建立一个大的where 并应用它?
  • 你确定吗?看起来您可以使用谓词创建 where 子句 - github.com/JohnEstropia/CoreStore/blob/…
  • 我不确定,查看您提供的链接看起来我们可以直接传递 NSPredicate,但是当我尝试使用代码 .where(NSCompoundPredicate.init(andPredicateWithSubpredicates: predicates)) 时,它会显示该错误。
  • 也许您使用的是不同的版本?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-04
  • 1970-01-01
  • 2023-03-10
  • 2020-07-13
相关资源
最近更新 更多